--- /dev/null
+#
+# ReactOS test applications makefile
+#
+
+PATH_TO_TOP = ../..
+
+include $(PATH_TO_TOP)/rules.mak
+
+
+# Test applications
+# alive apc args atomtest bench consume copymove count dump_shared_data
+# event file gditest hello isotest lpc mstest mutex nptest
+# pteb regtest sectest shm simple thread vmtest winhello
+TEST_APPS = alive apc args atomtest bench consume copymove count dump_shared_data \
+ event file gditest hello isotest lpc mstest mutex nptest \
+ pteb regtest sectest shm simple thread tokentest vmtest winhello dibtest \
+ lock hivetest
+
+TEST_MISC =
+
+all: $(TEST_APPS) $(TEST_MISC)
+
+depends:
+
+implib: $(TEST_APPS:%=%_implib) \
+ $(TEST_MISC:%=%_implib)
+
+clean: $(TEST_APPS:%=%_clean) \
+ $(TEST_MISC:%=%_clean)
+
+install: $(TEST_APPS:%=%_install) \
+ $(TEST_MISC:%=%_install)
+
+dist: $(TEST_APPS:%=%_dist) \
+ $(TEST_MISC:%=%_dist)
+
+.PHONY: all depends implib clean install dist
+
+
+#
+# Test Applications
+#
+$(TEST_APPS): %:
+ $(MAKE) -C $*
+
+$(TEST_APPS:%=%_implib): %_implib:
+ $(MAKE) -C $* implib
+
+$(TEST_APPS:%=%_clean): %_clean:
+ $(MAKE) -C $* clean
+
+$(TEST_APPS:%=%_dist): %_dist:
+ $(MAKE) -C $* dist
+
+$(TEST_APPS:%=%_install): %_install:
+ $(MAKE) -C $* install
+
+.PHONY: $(TEST_APPS) $(TEST_APPS:%=%_implib) $(TEST_APPS:%=%_clean) $(TEST_APPS:%=%_install) $(TEST_APPS:%=%_dist)
+
+
+#
+# Misc Test Applications
+#
+$(TEST_MISC): %:
+ $(MAKE) -C tests/$*
+
+$(TEST_MISC:%=%_implib): %_implib:
+ $(MAKE) -C tests/$* implib
+
+$(TEST_MISC:%=%_clean): %_clean:
+ $(MAKE) -C tests/$* clean
+
+$(TEST_MISC:%=%_dist): %_dist:
+ $(MAKE) -C tests/$* dist
+
+$(TEST_MISC:%=%_install): %_install:
+ $(MAKE) -C tests/$* install
+
+.PHONY: $(TEST_MISC) $(TEST_MISC:%=%_implib) $(TEST_MISC:%=%_clean) $(TEST_MISC:%=%_install) $(TEST_MISC:%=%_dist)
+
+
+etags:
+ find . -name "*.[ch]" -print | etags --language=c -
+
+# EOF
+
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.exe
+*.sym
--- /dev/null
+# $Id$
+
+PATH_TO_TOP = ../../..
+
+TARGET_NORC = yes
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = console
+
+TARGET_NAME = copymove
+
+TARGET_OBJECTS = $(TARGET_NAME).o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
--- /dev/null
+/*
+ * CopyFile, MoveFile and related routines test
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <tchar.h>
+#include <windows.h>
+
+static TCHAR
+FindOtherDrive()
+{
+ DWORD drives = GetLogicalDrives();
+ BOOL found = FALSE;
+ TCHAR drive;
+ TCHAR rootdir[] = _T( "?:\\" );
+ TCHAR currentdir[MAX_PATH + 1];
+
+ if (0 != GetCurrentDirectory(MAX_PATH + 1, currentdir)) {
+ for (drive = _T('A'); ! found && drive <= _T('Z'); drive++) {
+ if (0 != (drives & (1 << (drive - _T('A'))))&&
+ drive != _totupper(currentdir[0])) {
+ rootdir[0] = drive;
+ found = (DRIVE_FIXED == GetDriveType(rootdir));
+ }
+ }
+ }
+
+ return found ? drive - 1 : _T( ' ' );
+}
+
+static void
+DeleteTestFile(LPCTSTR filename)
+{
+ SetFileAttributes(filename, FILE_ATTRIBUTE_NORMAL);
+ DeleteFile(filename);
+}
+
+static void
+CreateTestFile(LPCTSTR filename, DWORD attributes)
+{
+ HANDLE file;
+ char buffer[4096];
+ DWORD wrote;
+ int c;
+
+ DeleteTestFile(filename);
+ file = CreateFile(filename,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ 0,
+ 0);
+
+ if (INVALID_HANDLE_VALUE == file) {
+ fprintf(stderr, "CreateFile failed with code %d\n", GetLastError());
+ exit(1);
+ }
+ for(c = 0; c < sizeof(buffer); c++) {
+ buffer[c] = (char) c;
+ }
+ if (! WriteFile(file, buffer, sizeof(buffer), &wrote, NULL)) {
+ fprintf(stderr, "WriteFile failed with code %d\n", GetLastError());
+ exit(1);
+ }
+ CloseHandle(file);
+
+ if (! SetFileAttributes(filename, attributes)) {
+ fprintf(stderr, "SetFileAttributes failed with code %d\n", GetLastError());
+ exit(1);
+ }
+}
+
+static void
+DeleteTestDir(LPCTSTR dirname)
+{
+ RemoveDirectory(dirname);
+}
+
+static void
+CreateTestDir(LPCTSTR dirname)
+{
+ if (! CreateDirectory(dirname, NULL)) {
+ fprintf(stderr, "CreateDirectory failed with code %d\n", GetLastError());
+ exit(1);
+ }
+}
+
+static void
+CheckTestFile(LPCTSTR filename, DWORD attributes)
+{
+ HANDLE file;
+ char buffer[4096];
+ DWORD read;
+ int c;
+ DWORD diskattr;
+
+ file = CreateFile(filename,
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ 0);
+
+ if (INVALID_HANDLE_VALUE == file) {
+ fprintf(stderr, "CreateFile failed with code %d\n", GetLastError());
+ exit(1);
+ }
+
+ if (! ReadFile(file, buffer, sizeof(buffer), &read, NULL)) {
+ fprintf(stderr, "ReadFile failed with code %d\n", GetLastError());
+ exit(1);
+ }
+ if (read != sizeof(buffer)) {
+ fprintf(stderr, "Trying to read %d bytes but got %d bytes\n", sizeof(buffer), read);
+ exit(1);
+ }
+ for(c = 0; c < sizeof(buffer); c++) {
+ if (buffer[c] != (char) c) {
+ fprintf(stderr, "File contents changed at position %d\n", c);
+ exit(1);
+ }
+ }
+
+ CloseHandle(file);
+
+ diskattr = GetFileAttributes(filename);
+ if (INVALID_FILE_ATTRIBUTES == diskattr) {
+ fprintf(stderr, "GetFileAttributes failed with code %d\n", GetLastError());
+ exit(1);
+ }
+ if (diskattr != attributes) {
+ fprintf(stderr, "Attribute mismatch, expected 0x%08x found 0x%08x\n", attributes, diskattr);
+ exit(1);
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ TCHAR otherdrive;
+ TCHAR otherfile[ ] = _T("?:\\other.dat");
+
+ otherdrive = FindOtherDrive();
+
+ printf("Testing simple move\n");
+ CreateTestFile(_T("begin.dat"), FILE_ATTRIBUTE_ARCHIVE);
+ DeleteTestFile(_T("end.dat"));
+ if (! MoveFile(_T("begin.dat"), _T("end.dat"))) {
+ fprintf(stderr, "MoveFile failed with code %d\n", GetLastError());
+ exit(1);
+ }
+ CheckTestFile(_T("end.dat"), FILE_ATTRIBUTE_ARCHIVE);
+ DeleteTestFile(_T("end.dat"));
+
+ printf("Testing move of non-existing file\n");
+ DeleteTestFile(_T("begin.dat"));
+ DeleteTestFile(_T("end.dat"));
+ if (MoveFile(_T("begin.dat"), _T("end.dat"))) {
+ fprintf(stderr, "MoveFile succeeded but shouldn't have\n");
+ exit(1);
+ } else if (ERROR_FILE_NOT_FOUND != GetLastError()) {
+ fprintf(stderr, "MoveFile failed with unexpected code %d\n", GetLastError());
+ exit(1);
+ }
+ DeleteTestFile(_T("end.dat"));
+
+/* Not correctly implemented in ros, destination file is kept open after this */
+#if 0
+ printf("Testing move to existing file\n");
+ CreateTestFile(_T("begin.dat"), FILE_ATTRIBUTE_ARCHIVE);
+ CreateTestFile(_T("end.dat"), FILE_ATTRIBUTE_ARCHIVE);
+ if (MoveFile(_T("begin.dat"), _T("end.dat"))) {
+ fprintf(stderr, "MoveFile succeeded but shouldn't have\n");
+ exit(1);
+ } else if (ERROR_ALREADY_EXISTS != GetLastError()) {
+ fprintf(stderr, "MoveFile failed with unexpected code %d\n", GetLastError());
+ exit(1);
+ }
+ DeleteTestFile(_T("begin.dat"));
+ DeleteTestFile(_T("end.dat"));
+#endif
+
+/* Not implemented yet in ros */
+#if 0
+ printf("Testing directory move\n");
+ CreateTestDir(_T("begin"));
+ CreateTestFile(_T("begin\\file.dat"), FILE_ATTRIBUTE_NORMAL);
+ DeleteTestDir(_T("end"));
+ if (! MoveFile(_T("begin"), _T("end"))) {
+ fprintf(stderr, "MoveFile failed with code %d\n", GetLastError());
+ exit(1);
+ }
+ CheckTestFile(_T("end\\file.dat"), FILE_ATTRIBUTE_NORMAL);
+ DeleteTestFile(_T("end\\file.dat"));
+ DeleteTestDir(_T("end"));
+#endif
+
+ printf("Testing file move to different directory\n");
+ CreateTestFile(_T("file.dat"), FILE_ATTRIBUTE_NORMAL);
+ CreateTestDir(_T("end"));
+ if (! MoveFile(_T("file.dat"), _T("end\\file.dat"))) {
+ fprintf(stderr, "MoveFile failed with code %d\n", GetLastError());
+ exit(1);
+ }
+ CheckTestFile(_T("end\\file.dat"), FILE_ATTRIBUTE_ARCHIVE);
+ DeleteTestFile(_T("end\\file.dat"));
+ DeleteTestDir(_T("end"));
+
+ printf("Testing move of read-only file\n");
+ CreateTestFile(_T("begin.dat"), FILE_ATTRIBUTE_READONLY);
+ DeleteTestFile(_T("end.dat"));
+ if (! MoveFile(_T("begin.dat"), _T("end.dat"))) {
+ fprintf(stderr, "MoveFile failed with code %d\n", GetLastError());
+ exit(1);
+ }
+ CheckTestFile(_T("end.dat"), FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY);
+ DeleteTestFile(_T("end.dat"));
+
+ printf("Testing move to different drive\n");
+ if (_T(' ') != otherdrive) {
+ otherfile[0] = otherdrive;
+ CreateTestFile(_T("begin.dat"), FILE_ATTRIBUTE_ARCHIVE);
+ DeleteTestFile(otherfile);
+ if (! MoveFile(_T("begin.dat"), otherfile)) {
+ fprintf(stderr, "MoveFile failed with code %d\n", GetLastError());
+ exit(1);
+ }
+ CheckTestFile(otherfile, FILE_ATTRIBUTE_ARCHIVE);
+ DeleteTestFile(otherfile);
+ } else {
+ printf(" Test skipped, no other drive available\n");
+ }
+
+ printf("Testing move/overwrite of existing file\n");
+ CreateTestFile(_T("begin.dat"), FILE_ATTRIBUTE_ARCHIVE);
+ CreateTestFile(_T("end.dat"), FILE_ATTRIBUTE_ARCHIVE);
+ if (! MoveFileEx(_T("begin.dat"), _T("end.dat"), MOVEFILE_REPLACE_EXISTING)) {
+ fprintf(stderr, "MoveFileEx failed with code %d\n", GetLastError());
+ exit(1);
+ }
+ DeleteTestFile(_T("begin.dat"));
+ DeleteTestFile(_T("end.dat"));
+
+/* Not (correctly) implemented in ros yet */
+#if 0
+ printf("Testing move/overwrite of existing readonly file\n");
+ CreateTestFile(_T("begin.dat"), FILE_ATTRIBUTE_ARCHIVE);
+ CreateTestFile(_T("end.dat"), FILE_ATTRIBUTE_READONLY);
+ if (MoveFileEx(_T("begin.dat"), _T("end.dat"), MOVEFILE_REPLACE_EXISTING)) {
+ fprintf(stderr, "MoveFileEx succeeded but shouldn't have\n");
+ exit(1);
+ } else if (ERROR_ALREADY_EXISTS != GetLastError() &&
+ ERROR_ACCESS_DENIED != GetLastError()) {
+ fprintf(stderr, "MoveFileEx failed with unexpected code %d\n", GetLastError());
+ exit(1);
+ }
+ DeleteTestFile(_T("begin.dat"));
+ DeleteTestFile(_T("end.dat"));
+#endif
+
+/* Not implemented in ros yet */
+#if 0
+ printf("Testing move to different drive without COPY_ALLOWED\n");
+ if (_T(' ') != otherdrive) {
+ otherfile[0] = otherdrive;
+ CreateTestFile(_T("begin.dat"), FILE_ATTRIBUTE_ARCHIVE);
+ DeleteTestFile(otherfile);
+ if (MoveFileEx(_T("begin.dat"), otherfile, 0)) {
+ fprintf(stderr, "MoveFileEx succeeded but shouldn't have\n");
+ exit(1);
+ } else if (ERROR_NOT_SAME_DEVICE != GetLastError()) {
+ fprintf(stderr, "MoveFileEx failed with unexpected code %d\n", GetLastError());
+ exit(1);
+ }
+ DeleteTestFile(otherfile);
+ } else {
+ printf(" Test skipped, no other drive available\n");
+ }
+#endif
+
+ printf("Testing move to different drive with COPY_ALLOWED\n");
+ if (_T(' ') != otherdrive) {
+ otherfile[0] = otherdrive;
+ CreateTestFile(_T("begin.dat"), FILE_ATTRIBUTE_ARCHIVE);
+ DeleteTestFile(otherfile);
+ if (! MoveFileEx(_T("begin.dat"), otherfile, MOVEFILE_COPY_ALLOWED)) {
+ fprintf(stderr, "MoveFileEx failed with code %d\n", GetLastError());
+ exit(1);
+ }
+ CheckTestFile(otherfile, FILE_ATTRIBUTE_ARCHIVE);
+ DeleteTestFile(otherfile);
+ } else {
+ printf(" Test skipped, no other drive available\n");
+ }
+
+ printf("All tests successfully completed\n");
+
+ return 0;
+}
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <windows.h>
+#include <ddk/ntddk.h>
+
+HANDLE OutputHandle;
+HANDLE InputHandle;
+
+void dprintf(char* fmt, ...)
+{
+ va_list args;
+ char buffer[255];
+
+ va_start(args,fmt);
+ vsprintf(buffer,fmt,args);
+ WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL);
+ va_end(args);
+}
+
+void do_enumeratekey(PWSTR Name)
+{
+ ULONG Index,Length,i;
+ KEY_BASIC_INFORMATION KeyInformation[5];
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE hKey1;
+ UNICODE_STRING KeyName;
+
+ RtlInitUnicodeString(&KeyName, Name);
+ InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE
+ , NULL, NULL);
+ Status=NtOpenKey( &hKey1, MAXIMUM_ALLOWED, &ObjectAttributes);
+ dprintf("NtEnumerateKey : \n");
+ Index=0;
+ while(Status == STATUS_SUCCESS)
+ {
+ Status=NtEnumerateKey(hKey1,Index++,KeyBasicInformation
+ ,&KeyInformation[0], sizeof(KeyInformation)
+ ,&Length);
+ if(Status== STATUS_SUCCESS)
+ {
+ dprintf("\tSubKey Name = ");
+ for (i=0;i<KeyInformation[0].NameLength/2;i++)
+ dprintf("%C",KeyInformation[0].Name[i]);
+ dprintf("\n");
+ }
+ }
+ NtClose(hKey1);
+}
+
+
+void CreateKeyTest(void)
+{
+ HKEY hKey;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName;
+ NTSTATUS Status;
+
+ dprintf("Create key: '\\Registry\\Machine\\Software\\testkey':\n");
+ RtlInitUnicodeStringFromLiteral(&KeyName,
+ L"\\Registry\\Machine\\Software\\testkey");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ dprintf("NtCreateKey: ");
+ Status = NtCreateKey(&hKey,
+ KEY_ALL_ACCESS,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ NULL);
+ dprintf("Status = %lx\n",Status);
+ if (NT_SUCCESS(Status))
+ {
+ NtClose(hKey);
+ }
+}
+
+
+void DeleteKeyTest(void)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName;
+ HKEY hKey;
+ NTSTATUS Status;
+
+ dprintf("Delete key '\\Registry\\Machine\\Software\\testkey':\n");
+ RtlInitUnicodeStringFromLiteral(&KeyName,
+ L"\\Registry\\Machine\\Software\\testkey");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ dprintf("NtOpenKey: ");
+ Status = NtOpenKey(&hKey,
+ KEY_ALL_ACCESS,
+ &ObjectAttributes);
+ dprintf("Status = %lx\n",Status);
+ if (!NT_SUCCESS(Status))
+ return;
+
+ dprintf("NtDeleteKey: ");
+ Status = NtDeleteKey(hKey);
+ dprintf("Status = %lx\n",Status);
+ NtClose(hKey);
+}
+
+
+void EnumerateKeyTest(void)
+{
+ HKEY hKey = NULL, hKey1;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ UNICODE_STRING KeyName;
+ ULONG Index;
+ ULONG Length;
+ ULONG i;
+ KEY_BASIC_INFORMATION KeyInformation[5];
+
+ dprintf("Enumerate key '\\Registry\\Machine\\Software':\n");
+ RtlInitUnicodeStringFromLiteral(&KeyName,
+ L"\\Registry\\Machine\\Software");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ dprintf("NtOpenKey: ");
+ Status = NtOpenKey(&hKey,
+ KEY_ALL_ACCESS,
+ &ObjectAttributes);
+ dprintf("Status = %lx\n", Status);
+ if (!NT_SUCCESS(Status))
+ return;
+
+ dprintf("NtQueryKey: ");
+ Status = NtQueryKey(hKey,
+ KeyBasicInformation,
+ &KeyInformation[0],
+ sizeof(KeyInformation),
+ &Length);
+ dprintf("Status = %lx\n", Status);
+ if (NT_SUCCESS(Status))
+ {
+ dprintf("\tKey Name = ");
+ for (i = 0; i < KeyInformation[0].NameLength / 2; i++)
+ dprintf("%C", KeyInformation[0].Name[i]);
+ dprintf("\n");
+ }
+
+ dprintf("NtEnumerateKey: \n");
+ Index=0;
+ while(NT_SUCCESS(Status))
+ {
+ Status = NtEnumerateKey(hKey,
+ Index,
+ KeyBasicInformation,
+ &KeyInformation[0],
+ sizeof(KeyInformation),
+ &Length);
+ if (NT_SUCCESS(Status))
+ {
+ dprintf("\tSubKey Name = ");
+ for (i = 0; i < KeyInformation[0].NameLength / 2; i++)
+ dprintf("%C", KeyInformation[0].Name[i]);
+ dprintf("\n");
+ }
+ Index++;
+ }
+
+ dprintf("NtClose: ");
+ Status = NtClose(hKey);
+ dprintf("Status = %lx\n", Status);
+}
+
+
+void SetValueTest1(void)
+{
+ HKEY hKey;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName;
+ UNICODE_STRING ValueName;
+ NTSTATUS Status;
+
+ dprintf("Create key: '\\Registry\\Machine\\Software\\testkey':\n");
+ RtlInitUnicodeStringFromLiteral(&KeyName,
+ L"\\Registry\\Machine\\Software\\testkey");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
+ NULL,
+ NULL);
+ dprintf("NtCreateKey: ");
+ Status = NtCreateKey(&hKey,
+ KEY_ALL_ACCESS,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ NULL);
+ dprintf("Status = %lx\n",Status);
+ if (!NT_SUCCESS(Status))
+ return;
+
+ RtlInitUnicodeStringFromLiteral(&ValueName,
+ L"TestValue");
+ dprintf("NtSetValueKey: ");
+ Status = NtSetValueKey(hKey,
+ &ValueName,
+ 0,
+ REG_SZ,
+ (PVOID)L"TestString",
+ 24);
+ dprintf("Status = %lx\n",Status);
+
+ NtClose(hKey);
+}
+
+
+void SetValueTest2(void)
+{
+ HKEY hKey;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName;
+ UNICODE_STRING ValueName;
+ NTSTATUS Status;
+
+ dprintf("Create key: '\\Registry\\Machine\\Software\\testkey':\n");
+ RtlInitUnicodeStringFromLiteral(&KeyName,
+ L"\\Registry\\Machine\\Software\\testkey");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
+ NULL,
+ NULL);
+ dprintf("NtCreateKey: ");
+ Status = NtCreateKey(&hKey,
+ KEY_ALL_ACCESS,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ NULL);
+ dprintf(" Status = %lx\n",Status);
+ if (!NT_SUCCESS(Status))
+ return;
+
+ RtlInitUnicodeStringFromLiteral(&ValueName,
+ L"TestValue");
+ dprintf("NtSetValueKey:\n");
+ Status = NtSetValueKey(hKey,
+ &ValueName,
+ 0,
+ REG_DWORD,
+ (PVOID)"reac",
+ 4);
+ dprintf(" Status = %lx\n",Status);
+
+ NtClose(hKey);
+}
+
+
+void DeleteValueTest(void)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName;
+ UNICODE_STRING ValueName;
+ HKEY KeyHandle;
+ NTSTATUS Status;
+
+ dprintf("Open key: '\\Registry\\Machine\\Software\\testkey':\n");
+ RtlInitUnicodeStringFromLiteral(&KeyName,
+ L"\\Registry\\Machine\\Software\\testkey");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status=NtOpenKey(&KeyHandle,
+ MAXIMUM_ALLOWED,
+ &ObjectAttributes);
+ dprintf(" Status = %lx\n", Status);
+ if (!NT_SUCCESS(Status))
+ return;
+
+ dprintf("Delete value:\n");
+ RtlInitUnicodeStringFromLiteral(&ValueName,
+ L"TestValue");
+ Status = NtDeleteValueKey(KeyHandle,
+ &ValueName);
+ dprintf(" Status = %lx\n", Status);
+
+ dprintf("Close key:\n");
+ Status = NtClose(KeyHandle);
+ dprintf(" Status = %lx\n", Status);
+}
+
+
+void EnumerateValueTest(void)
+{
+ KEY_VALUE_FULL_INFORMATION KeyValueInformation[5];
+ KEY_BASIC_INFORMATION KeyInformation[5];
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName;
+ ULONG Index,Length,i;
+ HKEY hKey = NULL;
+ NTSTATUS Status;
+
+ dprintf("Open key: '\\Registry\\Machine\\Software\\testkey':\n");
+ RtlInitUnicodeStringFromLiteral(&KeyName,
+ L"\\Registry\\Machine\\Software\\testkey");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status=NtOpenKey(&hKey,
+ MAXIMUM_ALLOWED,
+ &ObjectAttributes);
+ dprintf(" Status = %lx\n", Status);
+ if (!NT_SUCCESS(Status))
+ return;
+
+ dprintf("Enumerate values: \n");
+ Index = 0;
+ while (Status == STATUS_SUCCESS)
+ {
+ Status = NtEnumerateValueKey(hKey,
+ Index++,
+ KeyValueFullInformation,
+ &KeyValueInformation[0],
+ sizeof(KeyValueInformation),
+ &Length);
+ if (Status == STATUS_SUCCESS)
+ {
+ dprintf(" Value:DO=%d, DL=%d, NL=%d, Name = ",
+ KeyValueInformation[0].DataOffset,
+ KeyValueInformation[0].DataLength,
+ KeyValueInformation[0].NameLength);
+ for (i = 0; i < KeyValueInformation[0].NameLength / 2; i++)
+ dprintf("%C", KeyValueInformation[0].Name[i]);
+ dprintf(", Type = %d\n", KeyValueInformation[0].Type);
+
+ if (KeyValueInformation[0].Type == REG_SZ)
+ dprintf(" Value = %S\n",
+ ((char*)&KeyValueInformation[0]+KeyValueInformation[0].DataOffset));
+
+ if (KeyValueInformation[0].Type == REG_DWORD)
+ dprintf(" Value = %X\n",
+ *((DWORD*)((char*)&KeyValueInformation[0]+KeyValueInformation[0].DataOffset)));
+ }
+ }
+
+ dprintf("NtClose:\n");
+ Status = NtClose(hKey);
+ dprintf(" Status = %lx\n", Status);
+}
+
+
+
+
+void test1(void)
+{
+ HKEY hKey = NULL, hKey1;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+#if 0
+ UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry");
+#endif
+ UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry\\Machine\\Software");
+ ULONG Index,Length,i;
+ KEY_BASIC_INFORMATION KeyInformation[5];
+ KEY_VALUE_FULL_INFORMATION KeyValueInformation[5];
+
+#if 0
+ dprintf("NtOpenKey \\Registry : ");
+#endif
+ dprintf("NtOpenKey \\Registry\\Machine\\Software : ");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status=NtOpenKey( &hKey1, MAXIMUM_ALLOWED, &ObjectAttributes);
+ dprintf("\t\t\t\tStatus =%x\n",Status);
+ if(Status==0)
+ {
+ dprintf("NtQueryKey : ");
+ Status=NtQueryKey(hKey1,KeyBasicInformation
+ ,&KeyInformation[0], sizeof(KeyInformation)
+ ,&Length);
+ dprintf("\t\t\t\t\tStatus =%x\n",Status);
+ if (Status == STATUS_SUCCESS)
+ {
+ dprintf("\tKey Name = ");
+ for (i=0;i<KeyInformation[0].NameLength/2;i++)
+ dprintf("%C",KeyInformation[0].Name[i]);
+ dprintf("\n");
+ }
+ dprintf("NtEnumerateKey : \n");
+ Index=0;
+ while(Status == STATUS_SUCCESS)
+ {
+ Status=NtEnumerateKey(hKey1,Index++,KeyBasicInformation
+ ,&KeyInformation[0], sizeof(KeyInformation)
+ ,&Length);
+ if(Status== STATUS_SUCCESS)
+ {
+ dprintf("\tSubKey Name = ");
+ for (i=0;i<KeyInformation[0].NameLength/2;i++)
+ dprintf("%C",KeyInformation[0].Name[i]);
+ dprintf("\n");
+ }
+ }
+ dprintf("NtClose : ");
+ Status = NtClose( hKey1 );
+ dprintf("\t\t\t\t\tStatus =%x\n",Status);
+ }
+ NtClose(hKey);
+
+#if 0
+ dprintf("NtOpenKey \\Registry\\Machine : ");
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status=NtOpenKey( &hKey1, MAXIMUM_ALLOWED, &ObjectAttributes);
+ dprintf("\t\t\tStatus =%x\n",Status);
+
+ dprintf("NtOpenKey System\\Setup : ");
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"System\\Setup");
+ InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE
+ , hKey1 , NULL);
+ Status = NtOpenKey ( &hKey, KEY_READ , &ObjectAttributes);
+ dprintf("\t\t\tStatus =%x\n",Status);
+ if(Status==0)
+ {
+ dprintf("NtQueryValueKey : ");
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"CmdLine");
+ Status=NtQueryValueKey(hKey,&KeyName,KeyValueFullInformation
+ ,&KeyValueInformation[0], sizeof(KeyValueInformation)
+ ,&Length);
+ dprintf("\t\t\t\tStatus =%x\n",Status);
+ if (Status == STATUS_SUCCESS)
+ {
+ dprintf("\tValue:DO=%d, DL=%d, NL=%d, Name = "
+ ,KeyValueInformation[0].DataOffset
+ ,KeyValueInformation[0].DataLength
+ ,KeyValueInformation[0].NameLength);
+ for (i=0;i<10 && i<KeyValueInformation[0].NameLength/2;i++)
+ dprintf("%C",KeyValueInformation[0].Name[i]);
+ dprintf("\n");
+ dprintf("\t\tType = %d\n",KeyValueInformation[0].Type);
+ if (KeyValueInformation[0].Type == REG_SZ)
+ dprintf("\t\tValue = %S\n",
+ (PWCHAR)((PCHAR)&KeyValueInformation[0] + KeyValueInformation[0].DataOffset));
+ }
+ dprintf("NtEnumerateValueKey : \n");
+ Index=0;
+ while(Status == STATUS_SUCCESS)
+ {
+ Status=NtEnumerateValueKey(hKey,Index++,KeyValueFullInformation
+ ,&KeyValueInformation[0], sizeof(KeyValueInformation)
+ ,&Length);
+ if(Status== STATUS_SUCCESS)
+ {
+ dprintf("\tValue:DO=%d, DL=%d, NL=%d, Name = "
+ ,KeyValueInformation[0].DataOffset
+ ,KeyValueInformation[0].DataLength
+ ,KeyValueInformation[0].NameLength);
+ for (i=0;i<KeyValueInformation[0].NameLength/2;i++)
+ dprintf("%C",KeyValueInformation[0].Name[i]);
+ dprintf(", Type = %d\n",KeyValueInformation[0].Type);
+ if (KeyValueInformation[0].Type == REG_SZ)
+ dprintf("\t\tValue = %S\n",((char*)&KeyValueInformation[0]
+ +KeyValueInformation[0].DataOffset));
+ }
+ }
+ dprintf("NtClose : ");
+ Status = NtClose( hKey );
+ dprintf("\t\t\t\t\tStatus =%x\n",Status);
+ }
+ NtClose( hKey1 );
+#endif
+}
+
+
+void test3(void)
+{
+ HKEY hKey,hKey1;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName,ValueName;
+ NTSTATUS Status;
+ KEY_VALUE_FULL_INFORMATION KeyValueInformation[5];
+ ULONG Index,Length,i;
+ char Buffer[10];
+ DWORD Result;
+ dprintf("NtCreateKey non volatile: \n");
+ dprintf(" \\Registry\\Machine\\Software\\test3reactos: ");
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\Software\\test3reactos");
+ InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE
+ , NULL, NULL);
+ Status = NtCreateKey ( &hKey, KEY_ALL_ACCESS , &ObjectAttributes
+ ,0,NULL,REG_OPTION_NON_VOLATILE,NULL);
+ dprintf("\t\tStatus=%x\n",Status);
+ NtClose(hKey);
+#if 0
+ do_enumeratekey(L"\\Registry\\Machine\\Software");
+ dprintf("NtOpenKey: ");
+ Status=NtOpenKey( &hKey, MAXIMUM_ALLOWED, &ObjectAttributes);
+ dprintf("\t\tStatus=%x\n",Status);
+ NtClose(hKey);
+ dprintf(" ...\\test3 :");
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\Software\\test3reactos\\test3");
+ InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE
+ , NULL, NULL);
+ Status = NtCreateKey ( &hKey, KEY_ALL_ACCESS , &ObjectAttributes
+ ,0,NULL,REG_OPTION_NON_VOLATILE,NULL);
+ dprintf("\t\t\t\t\tStatus=%x\n",Status);
+ dprintf("NtOpenKey: ");
+ Status=NtOpenKey( &hKey1, MAXIMUM_ALLOWED, &ObjectAttributes);
+ dprintf("\t\tStatus=%x\n",Status);
+ NtClose(hKey);
+ dprintf(" ...\\testNonVolatile :");
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"TestNonVolatile");
+ InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE
+ , hKey1, NULL);
+ Status = NtCreateKey ( &hKey, KEY_ALL_ACCESS , &ObjectAttributes
+ ,0,NULL,REG_OPTION_NON_VOLATILE,NULL);
+ dprintf("\t\t\t\tStatus=%x\n",Status);
+ NtClose(hKey1);
+ RtlInitUnicodeStringFromLiteral(&ValueName, L"TestREG_SZ");
+ dprintf("NtSetValueKey reg_sz: ");
+ Status=NtSetValueKey(hKey,&ValueName,0,REG_SZ,(PVOID)L"Test Reg_sz",24);
+ dprintf("\t\t\t\tStatus=%x\n",Status);
+ RtlInitUnicodeStringFromLiteral(&ValueName, L"TestDWORD");
+ dprintf("NtSetValueKey reg_dword: ");
+ Status=NtSetValueKey(hKey,&ValueName,0,REG_DWORD,(PVOID)"reac",4);
+ dprintf("\t\t\tStatus=%x\n",Status);
+ NtClose(hKey);
+ dprintf("NtOpenKey \\Registry\\Machine\\Software\\test3reactos\\test3\\testNonVolatile : ");
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\Software\\test3reactos\\test3\\testNonVolatile");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status=NtOpenKey( &hKey, MAXIMUM_ALLOWED, &ObjectAttributes);
+ dprintf("\t\t\t\tStatus =%x\n",Status);
+ if(Status==0)
+ {
+ dprintf("NtEnumerateValueKey : \n");
+ Index=0;
+ while(Status == STATUS_SUCCESS)
+ {
+ Status=NtEnumerateValueKey(hKey,Index++,KeyValueFullInformation
+ ,&KeyValueInformation[0], sizeof(KeyValueInformation)
+ ,&Length);
+ if(Status== STATUS_SUCCESS)
+ {
+ dprintf("\tValue:DO=%d, DL=%d, NL=%d, Name = "
+ ,KeyValueInformation[0].DataOffset
+ ,KeyValueInformation[0].DataLength
+ ,KeyValueInformation[0].NameLength);
+ for (i=0;i<KeyValueInformation[0].NameLength/2;i++)
+ dprintf("%C",KeyValueInformation[0].Name[i]);
+ dprintf(", Type = %d\n",KeyValueInformation[0].Type);
+ if (KeyValueInformation[0].Type == REG_SZ)
+ dprintf("\t\tValue = %S\n",((char*)&KeyValueInformation[0]
+ +KeyValueInformation[0].DataOffset));
+ }
+ }
+ }
+ NtClose(hKey);
+#endif
+
+ dprintf("delete \\Registry\\Machine\\software\\test3reactos ?");
+ ReadConsoleA(InputHandle, Buffer, 3, &Result, NULL) ;
+ if (Buffer[0] != 'y' && Buffer[0] != 'Y') return;
+#if 0
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\Software\\test3reactos\\test3\\testNonvolatile");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ dprintf("NtOpenKey : ");
+ Status=NtOpenKey( &hKey, KEY_ALL_ACCESS, &ObjectAttributes);
+ dprintf("\t\t\t\tStatus =%x\n",Status);
+ dprintf("NtDeleteKey : ");
+ Status=NtDeleteKey(hKey);
+ dprintf("\t\t\t\tStatus =%x\n",Status);
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\Software\\test3reactos\\test3");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ dprintf("NtOpenKey : ");
+ Status=NtOpenKey( &hKey, KEY_ALL_ACCESS, &ObjectAttributes);
+ dprintf("\t\t\t\tStatus =%x\n",Status);
+ dprintf("NtDeleteKey : ");
+ Status=NtDeleteKey(hKey);
+ dprintf("\t\t\t\tStatus =%x\n",Status);
+ NtClose(hKey);
+#endif
+ dprintf("delete \\Registry\\Machine\\software\\test3reactos ?");
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\Software\\test3reactos");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ dprintf("NtOpenKey : ");
+ Status=NtOpenKey( &hKey, KEY_ALL_ACCESS, &ObjectAttributes);
+ dprintf("\t\t\t\tStatus =%x\n",Status);
+ dprintf("NtDeleteKey : ");
+ Status=NtDeleteKey(hKey);
+ dprintf("\t\t\t\tStatus =%x\n",Status);
+ NtClose(hKey);
+}
+
+void test4(void)
+{
+ HKEY hKey = NULL,hKey1;
+ DWORD dwDisposition;
+ DWORD dwError;
+ DWORD RegDataType, RegDataSize;
+ BOOL GlobalFifoEnable;
+ HKEY hPortKey;
+ DWORD RegDisposition;
+ WCHAR szClass[260];
+ DWORD cchClass;
+ DWORD cSubKeys;
+ DWORD cchMaxSubkey;
+ DWORD cchMaxClass;
+ DWORD cValues;
+ DWORD cchMaxValueName;
+ DWORD cbMaxValueData;
+ DWORD cbSecurityDescriptor;
+ FILETIME ftLastWriteTime;
+ SYSTEMTIME LastWriteTime;
+
+ dprintf ("RegOpenKeyExW HKLM\\System\\Setup: ");
+ dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"System\\Setup",
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey1);
+ dprintf("\t\tdwError =%x\n",dwError);
+ if (dwError == ERROR_SUCCESS)
+ {
+ dprintf("RegQueryInfoKeyW: ");
+ cchClass=260;
+ dwError = RegQueryInfoKeyW(hKey1
+ , szClass, &cchClass, NULL, &cSubKeys
+ , &cchMaxSubkey, &cchMaxClass, &cValues, &cchMaxValueName
+ , &cbMaxValueData, &cbSecurityDescriptor, &ftLastWriteTime);
+ dprintf ("\t\t\t\tdwError %x\n", dwError);
+ FileTimeToSystemTime(&ftLastWriteTime,&LastWriteTime);
+ dprintf ("\tnb of subkeys=%d,last write : %d/%d/%d %d:%02.2d'%02.2d''%03.3d\n",cSubKeys
+ ,LastWriteTime.wMonth
+ ,LastWriteTime.wDay
+ ,LastWriteTime.wYear
+ ,LastWriteTime.wHour
+ ,LastWriteTime.wMinute
+ ,LastWriteTime.wSecond
+ ,LastWriteTime.wMilliseconds
+ );
+ }
+
+
+ dprintf ("RegOpenKeyExW: ");
+ dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ L"System\\ControlSet001\\Services\\Serial",
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey);
+ dprintf ("\t\t\t\t\tdwError %x\n", dwError);
+ RegDataSize = sizeof(GlobalFifoEnable);
+ if (dwError == ERROR_SUCCESS)
+ {
+ dprintf ("RegQueryValueExW: ");
+ dwError = RegQueryValueExW(hKey,
+ L"ForceFifoEnable",
+ NULL,
+ &RegDataType,
+ (PBYTE)&GlobalFifoEnable,
+ &RegDataSize);
+ dprintf("\t\t\t\tdwError =%x\n",dwError);
+ if (dwError == 0)
+ {
+ dprintf("\tValue:DT=%d, DS=%d, Value=%d\n"
+ ,RegDataType
+ ,RegDataSize
+ ,GlobalFifoEnable);
+ }
+ }
+ dprintf ("RegCreateKeyExW: ");
+ dwError = RegCreateKeyExW(hKey,
+ L"Parameters\\Serial001",
+ 0,
+ NULL,
+ 0,
+ KEY_ALL_ACCESS,
+ NULL,
+ &hPortKey,
+ &RegDisposition
+ );
+ dprintf ("\t\t\t\tdwError %x\n", dwError);
+
+ dprintf ("RegCreateKeyExW: ");
+ dwError = RegCreateKeyExW (HKEY_LOCAL_MACHINE,
+ L"Software\\test4reactos\\test",
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ NULL,
+ &hKey,
+ &dwDisposition);
+
+ dprintf ("\t\t\t\tdwError %x ", dwError);
+ dprintf ("dwDisposition %x\n", dwDisposition);
+ if (dwError == ERROR_SUCCESS)
+ {
+ dprintf ("RegSetValueExW: ");
+ dwError = RegSetValueExW (hKey,
+ L"TestValue",
+ 0,
+ REG_SZ,
+ (BYTE*)L"TestString",
+ 20);
+
+ dprintf ("\t\t\t\tdwError %x\n", dwError);
+ dprintf ("RegCloseKey: ");
+ dwError = RegCloseKey (hKey);
+ dprintf ("\t\t\t\t\tdwError %x\n", dwError);
+ }
+ dprintf ("\n\n");
+
+ hKey = NULL;
+
+ dprintf ("RegCreateKeyExW: ");
+ dwError = RegCreateKeyExW (HKEY_LOCAL_MACHINE,
+ L"software\\Test",
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ KEY_ALL_ACCESS,
+ NULL,
+ &hKey,
+ &dwDisposition);
+
+ dprintf ("\t\t\t\tdwError %x ", dwError);
+ dprintf ("dwDisposition %x\n", dwDisposition);
+
+
+ if (dwError == ERROR_SUCCESS)
+ {
+ dprintf("RegQueryInfoKeyW: ");
+ cchClass=260;
+ dwError = RegQueryInfoKeyW(hKey
+ , szClass, &cchClass, NULL, &cSubKeys
+ , &cchMaxSubkey, &cchMaxClass, &cValues, &cchMaxValueName
+ , &cbMaxValueData, &cbSecurityDescriptor, &ftLastWriteTime);
+ dprintf ("\t\t\t\tdwError %x\n", dwError);
+ FileTimeToSystemTime(&ftLastWriteTime,&LastWriteTime);
+ dprintf ("\tnb of subkeys=%d,last write : %d/%d/%d %d:%02.2d'%02.2d''%03.3d\n",cSubKeys
+ ,LastWriteTime.wMonth
+ ,LastWriteTime.wDay
+ ,LastWriteTime.wYear
+ ,LastWriteTime.wHour
+ ,LastWriteTime.wMinute
+ ,LastWriteTime.wSecond
+ ,LastWriteTime.wMilliseconds
+ );
+ dprintf ("RegCloseKey: ");
+ dwError = RegCloseKey (hKey);
+ dprintf ("\t\t\t\t\tdwError %x\n", dwError);
+ }
+ dprintf ("\nTests done...\n");
+}
+
+void test5(void)
+{
+ HKEY hKey,hKey1;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName,ValueName;
+ NTSTATUS Status;
+ KEY_VALUE_FULL_INFORMATION KeyValueInformation[5];
+ ULONG Index,Length,i;
+ char Buffer[10];
+ DWORD Result;
+
+ dprintf("NtOpenKey : \n");
+ dprintf(" \\Registry\\Machine\\Software\\reactos : ");
+ RtlInitUnicodeStringFromLiteral(&KeyName,L"\\Registry\\Machine\\Software\\reactos");
+ InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE
+ , NULL, NULL);
+ Status=NtOpenKey( &hKey, KEY_ALL_ACCESS, &ObjectAttributes);
+ dprintf("\t\tStatus=%x\n",Status);
+ dprintf("NtFlushKey : \n");
+ Status = NtFlushKey(hKey);
+ dprintf("\t\tStatus=%x\n",Status);
+ dprintf("NtCloseKey : \n");
+ Status=NtClose(hKey);
+ dprintf("\t\tStatus=%x\n",Status);
+}
+
+/* registry link create test */
+void test6(void)
+{
+ HKEY hKey;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName,ValueName;
+ NTSTATUS Status;
+ KEY_VALUE_FULL_INFORMATION KeyValueInformation[5];
+ ULONG Index,Length,i;
+ char Buffer[10];
+ DWORD Result;
+
+ dprintf("Create target key\n");
+ dprintf(" Key: \\Registry\\Machine\\SOFTWARE\\Reactos\n");
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\SOFTWARE\\Reactos");
+ InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE
+ , NULL, NULL);
+ Status = NtCreateKey(&hKey, KEY_ALL_ACCESS , &ObjectAttributes
+ ,0,NULL, REG_OPTION_VOLATILE,NULL);
+ dprintf(" NtCreateKey() called (Status %lx)\n",Status);
+ if (!NT_SUCCESS(Status))
+ return;
+
+ dprintf("Create target value\n");
+ dprintf(" Value: TestValue = 'Test String'\n");
+ RtlInitUnicodeStringFromLiteral(&ValueName, L"TestValue");
+ Status=NtSetValueKey(hKey,&ValueName,0,REG_SZ,(PVOID)L"TestString",22);
+ dprintf(" NtSetValueKey() called (Status %lx)\n",Status);
+ if (!NT_SUCCESS(Status))
+ return;
+
+ dprintf("Close target key\n");
+ NtClose(hKey);
+
+
+ dprintf("Create link key\n");
+ dprintf(" Key: \\Registry\\Machine\\SOFTWARE\\Test\n");
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\SOFTWARE\\Test");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE | OBJ_OPENLINK,
+ NULL,
+ NULL);
+ Status = NtCreateKey(&hKey,
+ KEY_ALL_ACCESS | KEY_CREATE_LINK,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
+ NULL);
+ dprintf(" NtCreateKey() called (Status %lx)\n",Status);
+ if (!NT_SUCCESS(Status))
+ return;
+
+ dprintf("Create link value\n");
+ dprintf(" Value: SymbolicLinkValue = '\\Registry\\Machine\\SOFTWARE\\Reactos'\n");
+ RtlInitUnicodeStringFromLiteral(&ValueName, L"SymbolicLinkValue");
+ Status=NtSetValueKey(hKey,&ValueName,0,REG_LINK,(PVOID)L"\\Registry\\Machine\\SOFTWARE\\Reactos",68);
+ dprintf(" NtSetValueKey() called (Status %lx)\n",Status);
+ if (!NT_SUCCESS(Status))
+ {
+ dprintf("Creating link value failed! Test failed!\n");
+ NtClose(hKey);
+ return;
+ }
+
+ dprintf("Close link key\n");
+ NtClose(hKey);
+
+ dprintf("Open link key\n");
+ dprintf(" Key: \\Registry\\Machine\\SOFTWARE\\Test\n");
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\SOFTWARE\\Test");
+ InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF
+ , NULL, NULL);
+ Status = NtCreateKey(&hKey, KEY_ALL_ACCESS , &ObjectAttributes
+ ,0,NULL, REG_OPTION_VOLATILE, NULL);
+ dprintf(" NtCreateKey() called (Status %lx)\n",Status);
+ if (!NT_SUCCESS(Status))
+ return;
+
+ dprintf("Query value\n");
+ dprintf(" Value: TestValue\n");
+ RtlInitUnicodeStringFromLiteral(&ValueName, L"TestValue");
+ Status=NtQueryValueKey(hKey,
+ &ValueName,
+ KeyValueFullInformation,
+ &KeyValueInformation[0],
+ sizeof(KeyValueInformation),
+ &Length);
+ dprintf(" NtQueryValueKey() called (Status %lx)\n",Status);
+ if (Status == STATUS_SUCCESS)
+ {
+ dprintf(" Value: Type %d DataLength %d NameLength %d Name '",
+ KeyValueInformation[0].Type,
+ KeyValueInformation[0].DataLength,
+ KeyValueInformation[0].NameLength);
+ for (i=0; i < KeyValueInformation[0].NameLength / sizeof(WCHAR); i++)
+ dprintf("%C",KeyValueInformation[0].Name[i]);
+ dprintf("'\n");
+ if (KeyValueInformation[0].Type == REG_SZ)
+ dprintf(" Value '%S'\n",
+ KeyValueInformation[0].Name+1
+ +KeyValueInformation[0].NameLength/2);
+ }
+
+ dprintf("Close link key\n");
+ NtClose(hKey);
+
+ dprintf("Test successful!\n");
+}
+
+/* registry link delete test */
+void test7(void)
+{
+ HKEY hKey;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName,ValueName;
+ NTSTATUS Status;
+
+ dprintf("Open link key\n");
+ dprintf(" Key: \\Registry\\Machine\\SOFTWARE\\Test\n");
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine\\SOFTWARE\\Test");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_OPENLINK,
+ NULL,
+ NULL);
+ Status = NtCreateKey(&hKey,
+ KEY_ALL_ACCESS,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE | REG_OPTION_OPEN_LINK,
+ NULL);
+ dprintf(" NtCreateKey() called (Status %lx)\n",Status);
+ if (!NT_SUCCESS(Status))
+ {
+ dprintf("Could not open the link key. Please run the link create test first!\n");
+ return;
+ }
+
+ dprintf("Delete link value\n");
+ RtlInitUnicodeStringFromLiteral(&ValueName, L"SymbolicLinkValue");
+ Status = NtDeleteValueKey(hKey,
+ &ValueName);
+ dprintf(" NtDeleteValueKey() called (Status %lx)\n",Status);
+
+ dprintf("Delete link key\n");
+ Status=NtDeleteKey(hKey);
+ dprintf(" NtDeleteKey() called (Status %lx)\n",Status);
+
+ dprintf("Close link key\n");
+ NtClose(hKey);
+}
+
+
+void test8(void)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName;
+ NTSTATUS Status;
+ LONG dwError;
+ TOKEN_PRIVILEGES NewPrivileges;
+ HANDLE Token,hKey;
+ LUID Luid;
+ BOOLEAN bRes;
+ Status=NtOpenProcessToken(GetCurrentProcess()
+ ,TOKEN_ADJUST_PRIVILEGES,&Token);
+// ,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&Token);
+ dprintf("\t\t\t\tStatus =%x\n",Status);
+// bRes=LookupPrivilegeValueA(NULL,SE_RESTORE_NAME,&Luid);
+// dprintf("\t\t\t\tbRes =%x\n",bRes);
+ NewPrivileges.PrivilegeCount = 1;
+ NewPrivileges.Privileges[0].Luid = Luid;
+// NewPrivileges.Privileges[0].Luid.u.LowPart=18;
+// NewPrivileges.Privileges[0].Luid.u.HighPart=0;
+ NewPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+// Status = NtAdjustPrivilegesToken(
+ bRes = AdjustTokenPrivileges(
+ Token,
+ FALSE,
+ &NewPrivileges,
+ 0,
+ NULL,
+ NULL
+ );
+ dprintf("\t\t\t\tbRes =%x\n",bRes);
+
+// Status=NtClose(Token);
+// dprintf("\t\t\t\tStatus =%x\n",Status);
+
+
+ RtlInitUnicodeStringFromLiteral(&KeyName,L"test5");
+ InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE
+ , NULL, NULL);
+ Status = NtLoadKey(HKEY_LOCAL_MACHINE,&ObjectAttributes);
+ dprintf("\t\t\t\tStatus =%x\n",Status);
+ dwError=RegLoadKey(HKEY_LOCAL_MACHINE,"def"
+ ,"test5");
+ dprintf("\t\t\t\tdwError =%x\n",dwError);
+
+ dprintf("NtOpenKey \\Registry\\Machine : ");
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status=NtOpenKey( &hKey, MAXIMUM_ALLOWED, &ObjectAttributes);
+ dprintf("\t\t\tStatus =%x\n",Status);
+ RtlInitUnicodeStringFromLiteral(&KeyName,L"test5");
+ InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE
+ , NULL, NULL);
+ Status = NtLoadKey(hKey,&ObjectAttributes);
+ dprintf("\t\t\t\tStatus =%x\n",Status);
+}
+
+void test9(void)
+{
+ HKEY hKey = NULL, hKey1;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ UNICODE_STRING KeyName = UNICODE_STRING_INITIALIZER(L"\\Registry");
+ ULONG Index,Length,i;
+ KEY_BASIC_INFORMATION KeyInformation[5];
+ KEY_VALUE_FULL_INFORMATION KeyValueInformation[5];
+
+ dprintf("NtOpenKey \\Registry : ");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status=NtOpenKey( &hKey1, MAXIMUM_ALLOWED, &ObjectAttributes);
+ dprintf("\t\t\t\tStatus =%x\n",Status);
+ if (Status == 0) {
+ dprintf("NtQueryKey : ");
+ Status = NtQueryKey(hKey1, KeyBasicInformation, &KeyInformation[0], sizeof(KeyInformation), &Length);
+ dprintf("\t\t\t\t\tStatus =%x\n",Status);
+ if (Status == STATUS_SUCCESS) {
+ dprintf("\tKey Name = ");
+ for (i=0;i<KeyInformation[0].NameLength/2;i++)
+ dprintf("%C",KeyInformation[0].Name[i]);
+ dprintf("\n");
+ }
+
+ dprintf("NtEnumerateKey : \n");
+ Index = 0;
+ while (Status == STATUS_SUCCESS) {
+ Status = NtEnumerateKey(hKey1,Index++,KeyBasicInformation,&KeyInformation[0], sizeof(KeyInformation),&Length);
+ if (Status == STATUS_SUCCESS) {
+ dprintf("\tSubKey Name = ");
+ for (i = 0; i < KeyInformation[0].NameLength / 2; i++)
+ dprintf("%C",KeyInformation[0].Name[i]);
+ dprintf("\n");
+ }
+ }
+ dprintf("NtClose : ");
+ Status = NtClose( hKey1 );
+ dprintf("\t\t\t\t\tStatus =%x\n",Status);
+ }
+ NtClose(hKey); // RobD - hKey unused so-far, should this have been hKey1 ???
+
+ dprintf("NtOpenKey \\Registry\\Machine : ");
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"\\Registry\\Machine");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ Status = NtOpenKey(&hKey1, MAXIMUM_ALLOWED, &ObjectAttributes);
+ dprintf("\t\t\tStatus =%x\n",Status);
+
+//Status of c0000001 opening \Registry\Machine\System\CurrentControlSet\Services\Tcpip\Linkage
+
+// dprintf("NtOpenKey System\\CurrentControlSet\\Services\\Tcpip : ");
+// RtlInitUnicodeStringFromLiteral(&KeyName, L"System\\CurrentControlSet\\Services\\Tcpip");
+#if 1
+ dprintf("NtOpenKey System\\ControlSet001\\Services\\Tcpip\\Parameters : ");
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"System\\ControlSet001\\Services\\Tcpip\\Parameters");
+#else
+ dprintf("NtOpenKey System\\CurrentControlSet\\Services\\Tcpip : ");
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"System\\CurrentControlSet\\Services\\Tcpip");
+#endif
+ InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, hKey1 , NULL);
+ Status = NtOpenKey(&hKey, KEY_READ , &ObjectAttributes);
+ dprintf("\t\t\tStatus =%x\n",Status);
+ if (Status == 0) {
+ dprintf("NtQueryValueKey : ");
+ RtlInitUnicodeStringFromLiteral(&KeyName, L"NameServer");
+ Status = NtQueryValueKey(hKey, &KeyName, KeyValueFullInformation, &KeyValueInformation[0], sizeof(KeyValueInformation), &Length);
+ dprintf("\t\t\t\tStatus =%x\n",Status);
+ if (Status == STATUS_SUCCESS) {
+ dprintf("\tValue:DO=%d, DL=%d, NL=%d, Name = "
+ ,KeyValueInformation[0].DataOffset
+ ,KeyValueInformation[0].DataLength
+ ,KeyValueInformation[0].NameLength);
+ for (i = 0; i < 10 && i < KeyValueInformation[0].NameLength / 2; i++)
+ dprintf("%C", KeyValueInformation[0].Name[i]);
+ dprintf("\n");
+ dprintf("\t\tType = %d\n", KeyValueInformation[0].Type);
+ if (KeyValueInformation[0].Type == REG_SZ)
+ //dprintf("\t\tValue = %S\n", KeyValueInformation[0].Name + 1 + KeyValueInformation[0].NameLength / 2);
+ dprintf("\t\tValue = %S\n", KeyValueInformation[0].Name + KeyValueInformation[0].NameLength / 2);
+ }
+ dprintf("NtEnumerateValueKey : \n");
+ Index = 0;
+ while (Status == STATUS_SUCCESS) {
+ Status = NtEnumerateValueKey(hKey, Index++, KeyValueFullInformation, &KeyValueInformation[0], sizeof(KeyValueInformation), &Length);
+ if (Status == STATUS_SUCCESS) {
+ dprintf("\tValue:DO=%d, DL=%d, NL=%d, Name = "
+ ,KeyValueInformation[0].DataOffset
+ ,KeyValueInformation[0].DataLength
+ ,KeyValueInformation[0].NameLength);
+ for (i = 0; i < KeyValueInformation[0].NameLength / 2; i++)
+ dprintf("%C", KeyValueInformation[0].Name[i]);
+ dprintf(", Type = %d\n", KeyValueInformation[0].Type);
+ if (KeyValueInformation[0].Type == REG_SZ)
+ dprintf("\t\tValue = %S\n", ((char*)&KeyValueInformation[0]+KeyValueInformation[0].DataOffset));
+ if (KeyValueInformation[0].Type == REG_DWORD)
+ dprintf("\t\tValue = %X\n", *((DWORD*)((char*)&KeyValueInformation[0]+KeyValueInformation[0].DataOffset)));
+ }
+ }
+ dprintf("NtClose : ");
+ Status = NtClose(hKey);
+ dprintf("\t\t\t\t\tStatus =%x\n", Status);
+ }
+ NtClose(hKey1);
+}
+
+
+int main(int argc, char* argv[])
+{
+ char Buffer[10];
+ DWORD Result;
+
+ AllocConsole();
+ InputHandle = GetStdHandle(STD_INPUT_HANDLE);
+ OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
+ while(1)
+ {
+ dprintf("choose test :\n");
+ dprintf(" 0 = Exit\n");
+ dprintf(" 1 = Create key\n");
+ dprintf(" 2 = Delete key\n");
+ dprintf(" 3 = Enumerate key\n");
+ dprintf(" 4 = Set value (REG_SZ)\n");
+ dprintf(" 5 = Set value (REG_DWORD)\n");
+ dprintf(" 6 = Delete value\n");
+ dprintf(" 7 = Enumerate value\n");
+ ReadConsoleA(InputHandle, Buffer, 3, &Result, NULL) ;
+ switch (Buffer[0])
+ {
+ case '0':
+ return(0);
+
+ case '1':
+ CreateKeyTest();
+ break;
+
+ case '2':
+ DeleteKeyTest();
+ break;
+
+ case '3':
+ EnumerateKeyTest();
+ break;
+
+ case '4':
+ SetValueTest1();
+ break;
+
+ case '5':
+ SetValueTest2();
+ break;
+
+ case '6':
+ DeleteValueTest();
+ break;
+
+ case '7':
+ EnumerateValueTest();
+ break;
+ }
+ }
+ return(0);
+}
--- /dev/null
+#
+# $Id$
+
+PATH_TO_TOP = ../../..
+
+TARGET_NORC = yes
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = console
+
+TARGET_NAME = hivetest
+
+TARGET_SDKLIBS = ntdll.a kernel32.a
+
+TARGET_OBJECTS = $(TARGET_NAME).o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+# $Id$
+
+PATH_TO_TOP = ../../..
+
+TARGET_NORC = yes
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = console
+
+TARGET_NAME = lock
+
+TARGET_SDKLIBS = kernel32.a user32.a
+
+TARGET_OBJECTS = $(TARGET_NAME).o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
--- /dev/null
+
+#include <windows.h>
+#include <stdio.h>
+
+HANDLE hFile;
+
+BOOL Slock(DWORD start,DWORD len)
+{
+
+ OVERLAPPED overl;
+ BOOL stat;
+ overl.Offset = start;
+ overl.OffsetHigh = 0;
+ overl.hEvent = 0;
+
+
+ stat = LockFileEx(hFile,LOCKFILE_FAIL_IMMEDIATELY,0,len,0,&overl) ;
+ printf("Slock %i-%i %s\n",start,start+len,stat!=0 ? "OK" : "FAILED");
+ return stat;
+
+}
+
+BOOL Xlock(DWORD start,DWORD len)
+{
+
+ OVERLAPPED overl;
+ BOOL stat;
+
+ overl.Offset = start;
+ overl.OffsetHigh = 0;
+ overl.hEvent = 0;
+
+ stat = LockFileEx(hFile,LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,0,len,0,&overl);
+
+ printf("Xlock %i-%i %s\n",start,start+len,stat!=0 ? "OK" : "FAILED");
+ return stat;
+
+
+}
+
+BOOL unlock(DWORD start,DWORD len)
+{
+
+ OVERLAPPED overl;
+ BOOL stat;
+ overl.Offset = start;
+ overl.OffsetHigh = 0;
+ overl.hEvent = 0;
+
+ stat = UnlockFileEx(hFile,0,len,0,&overl) ;
+ printf("unlock %i-%i %s\n",start,start+len,stat!=0 ? "OK" : "FAILED");
+ return stat;
+
+}
+
+
+BOOL mkfile()
+{
+ hFile = CreateFile("C:\\lock.test",
+ GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ printf("mkfile %s\n",(hFile == INVALID_HANDLE_VALUE) ? "FAILED" : "OK");
+ return !(hFile == INVALID_HANDLE_VALUE);
+
+
+}
+
+void main(void)
+{
+ DWORD ass;
+
+ printf("enter main\n");
+
+ mkfile();
+
+ Slock(8,10);
+ Slock(10,5);
+ Slock(10,5);
+ Slock(15,5);
+ Slock(5,10);
+ Slock(0,100);
+ Xlock(30,10);
+ Xlock(30,1);
+ unlock(30,1);
+ unlock(30,10);
+ Xlock(30,5);
+ Slock(35,5);
+ unlock(50,5);
+ unlock(0,100);
+ unlock(10,5);
+
+ if (WriteFile(hFile,"ass",4,&ass,NULL) == 0) printf("write 1 failed\n");
+ else printf("write 1 success\n");
+
+ CloseHandle(hFile);
+ mkfile();
+ Slock(0,100);
+
+ if (WriteFile(hFile,"ass",4,&ass,NULL) == 0) printf("write 2 failed\n");
+ else printf("write 2 success\n");
+
+
+ CloseHandle(hFile);
+ Sleep(10000);
+
+
+}
\ No newline at end of file
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+// main.c :
+//
+#include <windows.h>
+#include <stdio.h>
+#include "regdump.h"
+
+
+HANDLE OutputHandle;
+HANDLE InputHandle;
+
+
+DWORD GetInput(char* Buffer, int buflen)
+{
+ DWORD Result;
+
+ ReadConsoleA(InputHandle, Buffer, buflen, &Result, NULL);
+ return Result;
+}
+
+int __cdecl main(int argc, char* argv[])
+{
+ //AllocConsole();
+ InputHandle = GetStdHandle(STD_INPUT_HANDLE);
+ OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
+ //return regmain(argc, argv);
+ return regdump(argc, argv);
+}
+
+
+#ifndef __GNUC__
+
+//__declspec(dllimport) int __stdcall DllMain(void* hinstDll, unsigned long dwReason, void* reserved);
+
+char* args[] = { "regdump.exe", "0", "ansi", "verbose"};
+
+int __cdecl mainCRTStartup(void)
+{
+
+ //DllMain(NULL, DLL_PROCESS_ATTACH, NULL);
+
+ main(1, args);
+ return 0;
+}
+
+#endif /*__GNUC__*/
--- /dev/null
+/* $Id$
+ *
+ * ReactOS regedit
+ *
+ * regcmds.c
+ *
+ * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
+ *
+ * Original Work Copyright 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_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#include <windows.h>
+#include <tchar.h>
+#include <stdio.h>
+
+#ifdef WIN32_REGDBG
+#else
+#include <ctype.h>
+#endif
+
+#include "regproc.h"
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Global Variables:
+//
+
+static char *usage =
+"Usage:\n"
+" regedit filename\n"
+" regedit /E filename [regpath]\n"
+" regedit /D regpath\n"
+"\n"
+"filename - registry file name\n"
+"regpath - name of the registry key\n"
+"\n"
+"When is called without any switches adds contents of the specified\n"
+"registry file to the registry\n"
+"\n"
+"Switches:\n"
+" /E - exports contents of the specified registry key to the specified\n"
+" file. Exports the whole registry if no key is specified.\n"
+" /D - deletes specified registry key\n"
+" /S - silent execution, can be used with any other switch.\n"
+" The only existing mode, exists for compatibility with Windows regedit.\n"
+" /V - advanced mode, can be used with any other switch.\n"
+" Ignored, exists for compatibility with Windows regedit.\n"
+" /L - location of system.dat file. Can be used with any other switch.\n"
+" Ignored. Exists for compatibility with Windows regedit.\n"
+" /R - location of user.dat file. Can be used with any other switch.\n"
+" Ignored. Exists for compatibility with Windows regedit.\n"
+" /? - print this help. Any other switches are ignored.\n"
+" /C - create registry from. Not implemented.\n"
+"\n"
+"The switches are case-insensitive, can be prefixed either by '-' or '/'.\n"
+"This program is command-line compatible with Microsoft Windows\n"
+"regedit. The difference with Windows regedit - this application has\n"
+"command-line interface only.\n";
+
+typedef enum {
+ ACTION_UNDEF, ACTION_ADD, ACTION_EXPORT, ACTION_DELETE, ACTION_VIEW
+} REGEDIT_ACTION;
+
+/**
+ * Process unknown switch.
+ *
+ * Params:
+ * chu - the switch character in upper-case.
+ * s - the command line string where s points to the switch character.
+ */
+void error_unknown_switch(char chu, char *s)
+{
+ if (isalpha(chu)) {
+ printf("Undefined switch /%c!\n", chu);
+ } else {
+ printf("Alphabetic character is expected after '%c' "
+ "in switch specification\n", *(s - 1));
+ }
+ //exit(1);
+}
+
+BOOL PerformRegAction(REGEDIT_ACTION action, LPSTR s)
+{
+ TCHAR filename[MAX_PATH];
+ TCHAR reg_key_name[KEY_MAX_LEN];
+
+ switch (action) {
+ case ACTION_ADD:
+ get_file_name(&s, filename, MAX_PATH);
+ if (!filename[0]) {
+ printf("No file name is specified\n%s", usage);
+ return FALSE;
+ //exit(1);
+ }
+ while (filename[0]) {
+ if (!import_registry_file(filename)) {
+ perror("");
+ printf("Can't open file \"%s\"\n", filename);
+ return FALSE;
+ //exit(1);
+ }
+ get_file_name(&s, filename, MAX_PATH);
+ }
+ break;
+ case ACTION_DELETE:
+ get_file_name(&s, reg_key_name, KEY_MAX_LEN);
+ if (!reg_key_name[0]) {
+ printf("No registry key is specified for removal\n%s", usage);
+ return FALSE;
+ //exit(1);
+ }
+ delete_registry_key(reg_key_name);
+ break;
+ case ACTION_EXPORT:
+ filename[0] = '\0';
+ get_file_name(&s, filename, MAX_PATH);
+ if (!filename[0]) {
+ printf("No file name is specified\n%s", usage);
+ return FALSE;
+ //exit(1);
+ }
+ if (s[0]) {
+ get_file_name(&s, reg_key_name, KEY_MAX_LEN);
+ export_registry_key(filename, reg_key_name);
+ } else {
+ export_registry_key(filename, NULL);
+ }
+ break;
+ default:
+ printf("Unhandled action!\n");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL ProcessCmdLine(LPSTR lpCmdLine)
+{
+ REGEDIT_ACTION action = ACTION_UNDEF;
+ LPSTR s = lpCmdLine; /* command line pointer */
+ CHAR ch = *s; /* current character */
+
+ while (ch && ((ch == '-') || (ch == '/'))) {
+ char chu;
+ char ch2;
+
+ s++;
+ ch = *s;
+ ch2 = *(s+1);
+ chu = toupper(ch);
+ if (!ch2 || isspace(ch2)) {
+ if (chu == 'S' || chu == 'V') {
+ /* ignore these switches */
+ } else {
+ switch (chu) {
+ case 'D':
+ action = ACTION_DELETE;
+ break;
+ case 'E':
+ action = ACTION_EXPORT;
+ break;
+ case 'V':
+ action = ACTION_VIEW;
+ break;
+ case '?':
+ printf(usage);
+ return FALSE;
+ //exit(0);
+ break;
+ default:
+ error_unknown_switch(chu, s);
+ return FALSE;
+ break;
+ }
+ }
+ s++;
+ } else {
+ if (ch2 == ':') {
+ switch (chu) {
+ case 'L':
+ /* fall through */
+ case 'R':
+ s += 2;
+ while (*s && !isspace(*s)) {
+ s++;
+ }
+ break;
+ default:
+ error_unknown_switch(chu, s);
+ return FALSE;
+ break;
+ }
+ } else {
+ /* this is a file name, starting from '/' */
+ s--;
+ break;
+ }
+ }
+ /* skip spaces to the next parameter */
+ ch = *s;
+ while (ch && isspace(ch)) {
+ s++;
+ ch = *s;
+ }
+ }
+ if (action == ACTION_UNDEF) {
+ action = ACTION_ADD;
+ }
+ return PerformRegAction(action, s);
+}
--- /dev/null
+/*
+ * ReactOS
+ *
+ * regdump.h
+ *
+ * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __REGDUMP_H__
+#define __REGDUMP_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern HANDLE OutputHandle;
+extern HANDLE InputHandle;
+
+DWORD GetInput(char* Buffer, int buflen);
+//void dprintf(char* fmt, ...);
+int regdump(int argc, char* argv[]);
+BOOL ProcessCmdLine(LPSTR lpCmdLine);
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // __REGDUMP_H__
--- /dev/null
+/*
+ * Registry processing routines. Routines, common for registry
+ * processing frontends.
+ *
+ * Copyright 1999 Sylvain St-Germain
+ * Copyright 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
+ */
+
+#ifdef WIN32_REGDBG
+#include <windows.h>
+#include <tchar.h>
+#ifndef __GNUC__
+#include <ntsecapi.h>
+#else
+#include <ctype.h>
+#endif
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+//#include <winreg.h>
+#include "regdump.h"
+#else
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#include <windows.h>
+#include <commctrl.h>
+#include <stdlib.h>
+#include <tchar.h>
+#include <process.h>
+#include <stdio.h>
+#include <wchar.h>
+
+#include <ctype.h>
+#include <limits.h>
+#include <winnt.h>
+#include <winreg.h>
+#include <assert.h>
+
+#endif
+
+#include "regproc.h"
+
+
+#define REG_VAL_BUF_SIZE 4096
+
+/* Delimiters used to parse the "value" to query queryValue*/
+#define QUERY_VALUE_MAX_ARGS 1
+
+/* maximal number of characters in hexadecimal data line,
+ not including '\' character */
+#define REG_FILE_HEX_LINE_LEN 76
+
+/* Globals used by the api setValue, queryValue */
+static LPTSTR currentKeyName = NULL;
+static HKEY currentKeyClass = 0;
+static HKEY currentKeyHandle = 0;
+static BOOL bTheKeyIsOpen = FALSE;
+
+static TCHAR *reg_class_names[] = {
+ _T("HKEY_LOCAL_MACHINE"),
+ _T("HKEY_USERS"),
+ _T("HKEY_CLASSES_ROOT"),
+ _T("HKEY_CURRENT_CONFIG"),
+ _T("HKEY_CURRENT_USER")
+};
+
+#define REG_CLASS_NUMBER (sizeof(reg_class_names) / sizeof(reg_class_names[0]))
+
+static HKEY reg_class_keys[REG_CLASS_NUMBER] = {
+ HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT,
+ HKEY_CURRENT_CONFIG, HKEY_CURRENT_USER
+};
+
+/* return values */
+#define NOT_ENOUGH_MEMORY 1
+#define IO_ERROR 2
+
+/* processing macros */
+
+/* common check of memory allocation results */
+#ifdef UNICODE
+#define CHECK_ENOUGH_MEMORY(p) \
+ if (!(p)) \
+ { \
+ _tprintf(_T("file %S, line %d: Not enough memory"), __FILE__, __LINE__); \
+ assert(0);\
+ exit(NOT_ENOUGH_MEMORY); \
+ }
+#else
+#define CHECK_ENOUGH_MEMORY(p) \
+ if (!(p)) \
+ { \
+ _tprintf(_T("file %s, line %d: Not enough memory"), __FILE__, __LINE__); \
+ assert(0);\
+ exit(NOT_ENOUGH_MEMORY); \
+ }
+#endif
+
+#ifdef UNICODE
+#define _TEOF WEOF
+#else
+#define _TEOF EOF
+#endif
+
+/******************************************************************************
+ * This is a replacement for strsep which is not portable (missing on Solaris).
+ */
+#if 0
+/* DISABLED */
+char* getToken(char** str, const char* delims)
+{
+ char* token;
+
+ if (*str==NULL) {
+ /* No more tokens */
+ return NULL;
+ }
+
+ token=*str;
+ while (**str!='\0') {
+ if (strchr(delims,**str)!=NULL) {
+ **str='\0';
+ (*str)++;
+ return token;
+ }
+ (*str)++;
+ }
+ /* There is no other token */
+ *str=NULL;
+ return token;
+}
+#endif
+
+/******************************************************************************
+ * Copies file name from command line string to the buffer.
+ * Rewinds the command line string pointer to the next non-spece character
+ * after the file name.
+ * Buffer contains an empty string if no filename was found;
+ *
+ * params:
+ * command_line - command line current position pointer
+ * where *s[0] is the first symbol of the file name.
+ * file_name - buffer to write the file name to.
+ */
+void get_file_nameA(CHAR **command_line, CHAR *file_name, int max_filename)
+{
+ CHAR *s = *command_line;
+ int pos = 0; /* position of pointer "s" in *command_line */
+ file_name[0] = 0;
+
+ if (!s[0]) {
+ return;
+ }
+ if (s[0] == '"') {
+ s++;
+ (*command_line)++;
+ while (s[0] != '"') {
+ if (!s[0]) {
+ _tprintf(_T("Unexpected end of file name!\n"));
+ assert(0);
+ //exit(1);
+ }
+ s++;
+ pos++;
+ }
+ } else {
+ while (s[0] && !isspace(s[0])) {
+ s++;
+ pos++;
+ }
+ }
+ memcpy(file_name, *command_line, pos * sizeof((*command_line)[0]));
+ /* remove the last backslash */
+ if (file_name[pos - 1] == '\\') {
+ file_name[pos - 1] = '\0';
+ } else {
+ file_name[pos] = '\0';
+ }
+ if (s[0]) {
+ s++;
+ pos++;
+ }
+ while (s[0] && isspace(s[0])) {
+ s++;
+ pos++;
+ }
+ (*command_line) += pos;
+}
+
+void get_file_nameW(CHAR** command_line, WCHAR* filename, int max_filename)
+{
+ CHAR filenameA[_MAX_PATH];
+ int len;
+
+ get_file_nameA(command_line, filenameA, _MAX_PATH);
+ len = strlen(filenameA);
+ OemToCharBuffW(filenameA, filename, max_filename);
+ filename[len] = _T('\0');
+/*
+ UNICODE_STRING UnicodeString;
+ ANSI_STRING AnsiString;
+ CHAR filenameA[_MAX_PATH];
+
+ get_file_nameA(command_line, filenameA, _MAX_PATH);
+
+ //RtlInitAnsiString(&AnsiString, filenameA);
+ UnicodeString.Buffer = filename;
+ UnicodeString.MaximumLength = max_filename;//MAX_PATH;
+ RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE);
+ */
+}
+
+/******************************************************************************
+ * Converts a hex representation of a DWORD into a DWORD.
+ */
+DWORD convertHexToDWord(TCHAR* str, BYTE* buf)
+{
+ DWORD dw;
+ TCHAR xbuf[9];
+
+ memcpy(xbuf, str, 8 * sizeof(TCHAR));
+ xbuf[88 * sizeof(TCHAR)] = '\0';
+ _stscanf(xbuf, _T("%08lx"), &dw);
+ memcpy(buf, &dw, sizeof(DWORD));
+ return sizeof(DWORD);
+}
+
+/******************************************************************************
+ * Converts a hex buffer into a hex comma separated values
+ */
+TCHAR* convertHexToHexCSV(BYTE* buf, ULONG bufLen)
+{
+ TCHAR* str;
+ TCHAR* ptrStr;
+ BYTE* ptrBuf;
+
+ ULONG current = 0;
+ str = HeapAlloc(GetProcessHeap(), 0, (bufLen+1)*2*sizeof(TCHAR));
+ memset(str, 0, (bufLen+1)*2);
+ ptrStr = str; /* Pointer to result */
+ ptrBuf = buf; /* Pointer to current */
+ while (current < bufLen) {
+ BYTE bCur = ptrBuf[current++];
+ TCHAR res[3];
+ _stprintf(res, _T("%02x"), (unsigned int)*&bCur);
+ _tcscat(str, res);
+ _tcscat(str, _T(","));
+ }
+ /* Get rid of the last comma */
+ str[_tcslen(str)-1] = _T('\0');
+ return str;
+}
+
+/******************************************************************************
+ * Converts a hex buffer into a DWORD string
+ */
+TCHAR* convertHexToDWORDStr(BYTE* buf, ULONG bufLen)
+{
+ TCHAR* str;
+ DWORD dw;
+
+ if (bufLen != sizeof(DWORD)) return NULL;
+ str = HeapAlloc(GetProcessHeap(), 0, ((bufLen*2)+1)*sizeof(TCHAR));
+ memcpy(&dw, buf, sizeof(DWORD));
+ _stprintf(str, _T("%08lx"), dw);
+ /* Get rid of the last comma */
+ return str;
+}
+
+/******************************************************************************
+ * Converts a hex comma separated values list into a hex list.
+ * The Hex input string must be in exactly the correct form.
+ */
+DWORD convertHexCSVToHex(TCHAR* str, BYTE* buf, ULONG bufLen)
+{
+ TCHAR* s = str; /* Pointer to current */
+ CHAR* b = buf; /* Pointer to result */
+ ULONG strLen = _tcslen(str);
+ ULONG strPos = 0;
+ DWORD byteCount = 0;
+
+ memset(buf, 0, bufLen);
+ /*
+ * warn the user if we are here with a string longer than 2 bytes that does
+ * not contains ",". It is more likely because the data is invalid.
+ */
+ if ((strLen > 2) && (_tcschr(str, _T(',')) == NULL)) {
+ _tprintf(_T("WARNING converting CSV hex stream with no comma, ") \
+ _T("input data seems invalid.\n"));
+ }
+ if (strLen > 3*bufLen) {
+ _tprintf(_T("ERROR converting CSV hex stream. Too long\n"));
+ }
+ while (strPos < strLen) {
+ TCHAR xbuf[3];
+ TCHAR wc;
+ memcpy(xbuf, s, 2);
+ xbuf[3] = _T('\0');
+ _stscanf(xbuf, _T("%02x"), (UINT*)&wc);
+ if (byteCount < bufLen)
+ *b++ = (unsigned char)wc;
+ s += 3;
+ strPos += 3;
+ ++byteCount;
+ }
+ return byteCount;
+}
+
+/******************************************************************************
+ * This function returns the HKEY associated with the data type encoded in the
+ * value. It modifies the input parameter (key value) in order to skip this
+ * "now useless" data type information.
+ *
+ * Note: Updated based on the algorithm used in 'server/registry.c'
+ */
+DWORD getDataType(LPTSTR* lpValue, DWORD* parse_type)
+{
+ struct data_type { const TCHAR *tag; int len; int type; int parse_type; };
+
+ static const struct data_type data_types[] =
+ { /* actual type */ /* type to assume for parsing */
+ { _T("\""), 1, REG_SZ, REG_SZ },
+ { _T("str:\""), 5, REG_SZ, REG_SZ },
+// { _T("str(2):\""), 8, REG_EXPAND_SZ, REG_SZ },
+ { _T("expand:\""), 8, REG_EXPAND_SZ, REG_EXPAND_SZ },
+ { _T("hex:"), 4, REG_BINARY, REG_BINARY },
+ { _T("dword:"), 6, REG_DWORD, REG_DWORD },
+ { _T("hex("), 4, -1, REG_BINARY },
+ { NULL, 0, 0, 0 }
+ };
+
+ const struct data_type *ptr;
+ int type;
+
+ for (ptr = data_types; ptr->tag; ptr++) {
+ if (memcmp(ptr->tag, *lpValue, ptr->len))
+ continue;
+
+ /* Found! */
+ *parse_type = ptr->parse_type;
+ type = ptr->type;
+ *lpValue += ptr->len;
+ if (type == -1) {
+ TCHAR* end;
+ /* "hex(xx):" is special */
+ type = (int)_tcstoul(*lpValue , &end, 16);
+ if (**lpValue == _T('\0') || *end != _T(')') || *(end+1) != _T(':')) {
+ type = REG_NONE;
+ } else {
+ *lpValue = end + 2;
+ }
+ }
+ return type;
+ }
+ return (**lpValue == _T('\0') ? REG_SZ : REG_NONE);
+}
+
+/******************************************************************************
+ * Returns an allocated buffer with a cleaned copy (removed the surrounding
+ * dbl quotes) of the passed value.
+ */
+LPTSTR getArg(LPTSTR arg)
+{
+ LPTSTR tmp = NULL;
+ ULONG len;
+
+ if (arg == NULL) return NULL;
+
+ // Get rid of surrounding quotes
+ len = _tcslen(arg);
+ if (arg[len-1] == _T('\"')) arg[len-1] = _T('\0');
+ if (arg[0] == _T('\"')) arg++;
+ tmp = HeapAlloc(GetProcessHeap(), 0, (_tcslen(arg)+1) * sizeof(TCHAR));
+ _tcscpy(tmp, arg);
+ return tmp;
+}
+
+/******************************************************************************
+ * Replaces escape sequences with the characters.
+ */
+void REGPROC_unescape_string(LPTSTR str)
+{
+ int str_idx = 0; /* current character under analysis */
+ int val_idx = 0; /* the last character of the unescaped string */
+ int len = _tcslen(str);
+ for (str_idx = 0; str_idx < len; str_idx++, val_idx++) {
+ if (str[str_idx] == _T('\\')) {
+ str_idx++;
+ switch (str[str_idx]) {
+ case _T('n'):
+ str[val_idx] = _T('\n');
+ break;
+ case _T('\\'):
+ case _T('"'):
+ str[val_idx] = str[str_idx];
+ break;
+ default:
+ _tprintf(_T("Warning! Unrecognized escape sequence: \\%c'\n"), str[str_idx]);
+ str[val_idx] = str[str_idx];
+ break;
+ }
+ } else {
+ str[val_idx] = str[str_idx];
+ }
+ }
+ str[val_idx] = _T('\0');
+}
+
+/******************************************************************************
+ * Sets the value with name val_name to the data in val_data for the currently
+ * opened key.
+ *
+ * Parameters:
+ * val_name - name of the registry value
+ * val_data - registry value data
+ */
+HRESULT setValue(LPTSTR val_name, LPTSTR val_data)
+{
+ HRESULT hRes;
+ DWORD dwDataType, dwParseType;
+ LPBYTE lpbData;
+ BYTE convert[KEY_MAX_LEN];
+ BYTE *bBigBuffer = 0;
+ DWORD dwLen;
+
+ if ((val_name == NULL) || (val_data == NULL))
+ return ERROR_INVALID_PARAMETER;
+
+ /* Get the data type stored into the value field */
+ dwDataType = getDataType(&val_data, &dwParseType);
+
+// if (dwParseType == REG_EXPAND_SZ) {
+// }
+// if (dwParseType == REG_SZ || dwParseType == REG_EXPAND_SZ) { /* no conversion for string */
+
+ if (dwParseType == REG_SZ) { /* no conversion for string */
+ dwLen = _tcslen(val_data);
+ if (dwLen > 0 && val_data[dwLen-1] == _T('"')) {
+ dwLen--;
+ val_data[dwLen] = _T('\0');
+ }
+ dwLen++;
+ dwLen *= sizeof(TCHAR);
+ REGPROC_unescape_string(val_data);
+ lpbData = val_data;
+ } else if (dwParseType == REG_DWORD) { /* Convert the dword types */
+ dwLen = convertHexToDWord(val_data, convert);
+ lpbData = convert;
+ } else { /* Convert the hexadecimal types */
+ int b_len = _tcslen(val_data)+2/3;
+ if (b_len > KEY_MAX_LEN) {
+ bBigBuffer = HeapAlloc (GetProcessHeap(), 0, b_len * sizeof(TCHAR));
+ if (bBigBuffer == NULL) {
+ return ERROR_REGISTRY_IO_FAILED;
+ }
+ CHECK_ENOUGH_MEMORY(bBigBuffer);
+ dwLen = convertHexCSVToHex(val_data, bBigBuffer, b_len);
+ lpbData = bBigBuffer;
+ } else {
+ dwLen = convertHexCSVToHex(val_data, convert, KEY_MAX_LEN);
+ lpbData = convert;
+ }
+ }
+ hRes = RegSetValueEx(currentKeyHandle, val_name,
+ 0, /* Reserved */dwDataType, lpbData, dwLen);
+
+ _tprintf(_T(" Value: %s, Data: %s\n"), val_name, lpbData);
+
+
+ if (bBigBuffer)
+ HeapFree(GetProcessHeap(), 0, bBigBuffer);
+ return hRes;
+}
+
+
+/******************************************************************************
+ * Open the key
+ */
+HRESULT openKey(LPTSTR stdInput)
+{
+ DWORD dwDisp;
+ HRESULT hRes;
+
+ /* Sanity checks */
+ if (stdInput == NULL)
+ return ERROR_INVALID_PARAMETER;
+
+ /* Get the registry class */
+ currentKeyClass = getRegClass(stdInput); /* Sets global variable */
+ if (currentKeyClass == (HKEY)ERROR_INVALID_PARAMETER)
+ return (HRESULT)ERROR_INVALID_PARAMETER;
+
+ /* Get the key name */
+ currentKeyName = getRegKeyName(stdInput); /* Sets global variable */
+ if (currentKeyName == NULL)
+ return ERROR_INVALID_PARAMETER;
+
+ hRes = RegCreateKeyEx(
+ currentKeyClass, /* Class */
+ currentKeyName, /* Sub Key */
+ 0, /* MUST BE 0 */
+ NULL, /* object type */
+ REG_OPTION_NON_VOLATILE, /* option, REG_OPTION_NON_VOLATILE ... */
+ KEY_ALL_ACCESS, /* access mask, KEY_ALL_ACCESS */
+ NULL, /* security attribute */
+ ¤tKeyHandle, /* result */
+ &dwDisp); /* disposition, REG_CREATED_NEW_KEY or
+ REG_OPENED_EXISTING_KEY */
+
+ if (hRes == ERROR_SUCCESS)
+ bTheKeyIsOpen = TRUE;
+
+ return hRes;
+
+}
+
+/******************************************************************************
+ * Extracts from [HKEY\some\key\path] or HKEY\some\key\path types of line
+ * the key name (what starts after the first '\')
+ */
+LPTSTR getRegKeyName(LPTSTR lpLine)
+{
+ LPTSTR keyNameBeg;
+ TCHAR lpLineCopy[KEY_MAX_LEN];
+
+ if (lpLine == NULL)
+ return NULL;
+
+ _tcscpy(lpLineCopy, lpLine);
+ keyNameBeg = _tcschr(lpLineCopy, _T('\\')); /* The key name start by '\' */
+ if (keyNameBeg) {
+ LPTSTR keyNameEnd;
+
+ keyNameBeg++; /* is not part of the name */
+ keyNameEnd = _tcschr(lpLineCopy, _T(']'));
+ if (keyNameEnd) {
+ *keyNameEnd = _T('\0'); /* remove ']' from the key name */
+ }
+ } else {
+ keyNameBeg = lpLineCopy + _tcslen(lpLineCopy); /* branch - empty string */
+ }
+ currentKeyName = HeapAlloc(GetProcessHeap(), 0, (_tcslen(keyNameBeg)+1)*sizeof(TCHAR));
+ CHECK_ENOUGH_MEMORY(currentKeyName);
+ _tcscpy(currentKeyName, keyNameBeg);
+ return currentKeyName;
+}
+
+/******************************************************************************
+ * Extracts from [HKEY\some\key\path] or HKEY\some\key\path types of line
+ * the key class (what ends before the first '\')
+ */
+HKEY getRegClass(LPTSTR lpClass)
+{
+ LPTSTR classNameEnd;
+ LPTSTR classNameBeg;
+ int i;
+
+ TCHAR lpClassCopy[KEY_MAX_LEN];
+
+ if (lpClass == NULL)
+ return (HKEY)ERROR_INVALID_PARAMETER;
+
+ _tcsncpy(lpClassCopy, lpClass, KEY_MAX_LEN);
+
+ classNameEnd = _tcschr(lpClassCopy, _T('\\')); /* The class name ends by '\' */
+ if (!classNameEnd) { /* or the whole string */
+ classNameEnd = lpClassCopy + _tcslen(lpClassCopy);
+ if (classNameEnd[-1] == _T(']')) {
+ classNameEnd--;
+ }
+ }
+ *classNameEnd = _T('\0'); /* Isolate the class name */
+ if (lpClassCopy[0] == _T('[')) {
+ classNameBeg = lpClassCopy + 1;
+ } else {
+ classNameBeg = lpClassCopy;
+ }
+ for (i = 0; i < REG_CLASS_NUMBER; i++) {
+ if (!_tcscmp(classNameBeg, reg_class_names[i])) {
+ return reg_class_keys[i];
+ }
+ }
+ return (HKEY)ERROR_INVALID_PARAMETER;
+}
+
+/******************************************************************************
+ * Close the currently opened key.
+ */
+void closeKey(VOID)
+{
+ RegCloseKey(currentKeyHandle);
+ HeapFree(GetProcessHeap(), 0, currentKeyName); /* Allocated by getKeyName */
+ bTheKeyIsOpen = FALSE;
+ currentKeyName = NULL;
+ currentKeyClass = 0;
+ currentKeyHandle = 0;
+}
+
+/******************************************************************************
+ * This function is the main entry point to the setValue type of action. It
+ * receives the currently read line and dispatch the work depending on the
+ * context.
+ */
+void doSetValue(LPTSTR stdInput)
+{
+ /*
+ * We encountered the end of the file, make sure we
+ * close the opened key and exit
+ */
+ if (stdInput == NULL) {
+ if (bTheKeyIsOpen != FALSE)
+ closeKey();
+ return;
+ }
+
+ if (stdInput[0] == _T('[')) { /* We are reading a new key */
+ if (bTheKeyIsOpen != FALSE) {
+ closeKey(); /* Close the previous key before */
+ }
+ if (openKey(stdInput) != ERROR_SUCCESS) {
+ _tprintf(_T("doSetValue failed to open key %s\n"), stdInput);
+ }
+ } else if ((bTheKeyIsOpen) &&
+ ((stdInput[0] == _T('@')) || /* reading a default @=data pair */
+ (stdInput[0] == _T('\"')))) { /* reading a new value=data pair */
+ processSetValue(stdInput);
+ } else { /* since we are assuming that the file format is */
+ if (bTheKeyIsOpen) /* valid we must be reading a blank line which */
+ closeKey(); /* indicate end of this key processing */
+ }
+}
+
+/******************************************************************************
+ * This funtion is the main entry point to the queryValue type of action. It
+ * receives the currently read line and dispatch the work depending on the
+ * context.
+ */
+void doQueryValue(LPTSTR stdInput) {
+ /*
+ * We encoutered the end of the file, make sure we
+ * close the opened key and exit
+ */
+ if (stdInput == NULL) {
+ if (bTheKeyIsOpen != FALSE)
+ closeKey();
+ return;
+ }
+
+ if (stdInput[0] == _T('[')) { /* We are reading a new key */
+ if (bTheKeyIsOpen != FALSE)
+ closeKey(); /* Close the previous key before */
+ if (openKey(stdInput) != ERROR_SUCCESS ) {
+ _tprintf(_T("doQueryValue failed to open key %s\n"), stdInput);
+ }
+ }
+ else if( (bTheKeyIsOpen) &&
+ ((stdInput[0] == _T('@')) || /* reading a default @=data pair */
+ (stdInput[0] == _T('\"')))) { /* reading a new value=data pair */
+ processQueryValue(stdInput);
+ } else { /* since we are assuming that the file format is */
+ if (bTheKeyIsOpen) /* valid we must be reading a blank line which */
+ closeKey(); /* indicate end of this key processing */
+ }
+}
+
+/******************************************************************************
+ * This funtion is the main entry point to the deletetValue type of action. It
+ * receives the currently read line and dispatch the work depending on the
+ * context.
+ */
+void doDeleteValue(LPTSTR line) {
+ _tprintf(_T("deleteValue not yet implemented\n"));
+}
+
+/******************************************************************************
+ * This funtion is the main entry point to the deleteKey type of action. It
+ * receives the currently read line and dispatch the work depending on the
+ * context.
+ */
+void doDeleteKey(LPTSTR line) {
+ _tprintf(_T("deleteKey not yet implemented\n"));
+}
+
+/******************************************************************************
+ * This funtion is the main entry point to the createKey type of action. It
+ * receives the currently read line and dispatch the work depending on the
+ * context.
+ */
+void doCreateKey(LPTSTR line) {
+ _tprintf(_T("createKey not yet implemented\n"));
+}
+
+/******************************************************************************
+ * This function is a wrapper for the setValue function. It prepares the
+ * land and clean the area once completed.
+ * Note: this function modifies the line parameter.
+ *
+ * line - registry file unwrapped line. Should have the registry value name and
+ * complete registry value data.
+ */
+void processSetValue(LPTSTR line)
+{
+ LPTSTR val_name; /* registry value name */
+ LPTSTR val_data; /* registry value data */
+
+ int line_idx = 0; /* current character under analysis */
+ HRESULT hRes = 0;
+
+ /* get value name */
+ if (line[line_idx] == _T('@') && line[line_idx + 1] == _T('=')) {
+ line[line_idx] = _T('\0');
+ val_name = line;
+ line_idx++;
+ } else if (line[line_idx] == _T('\"')) {
+ line_idx++;
+ val_name = line + line_idx;
+ while (TRUE) {
+ if (line[line_idx] == _T('\\')) { /* skip escaped character */
+ line_idx += 2;
+ } else {
+ if (line[line_idx] == _T('\"')) {
+ line[line_idx] = _T('\0');
+ line_idx++;
+ break;
+ } else {
+ line_idx++;
+ }
+ }
+ }
+ if (line[line_idx] != _T('=')) {
+ line[line_idx] = _T('\"');
+ _tprintf(_T("Warning! uncrecognized line:\n%s\n"), line);
+ return;
+ }
+ } else {
+ _tprintf(_T("Warning! unrecognized line:\n%s\n"), line);
+ return;
+ }
+ line_idx++; /* skip the '=' character */
+ val_data = line + line_idx;
+ REGPROC_unescape_string(val_name);
+
+ _tprintf(_T("Key: %s, Value: %s, Data: %s\n"), currentKeyName, val_name, val_data);
+
+ hRes = setValue(val_name, val_data);
+ if (hRes != ERROR_SUCCESS) {
+ _tprintf(_T("ERROR Key %s not created. Value: %s, Data: %s\n"), currentKeyName, val_name, val_data);
+ }
+}
+
+/******************************************************************************
+ * This function is a wrapper for the queryValue function. It prepares the
+ * land and clean the area once completed.
+ */
+void processQueryValue(LPTSTR cmdline)
+{
+ _tprintf(_T("ERROR!!! - temporary disabled"));
+ //exit(1);
+ return;
+#if 0
+ LPSTR argv[QUERY_VALUE_MAX_ARGS];/* args storage */
+ LPSTR token = NULL; /* current token analized */
+ ULONG argCounter = 0; /* counter of args */
+ INT counter;
+ HRESULT hRes = 0;
+ LPSTR keyValue = NULL;
+ LPSTR lpsRes = NULL;
+
+ /*
+ * Init storage and parse the line
+ */
+ for (counter = 0; counter < QUERY_VALUE_MAX_ARGS; counter++)
+ argv[counter] = NULL;
+
+ while ((token = getToken(&cmdline, queryValueDelim[argCounter])) != NULL) {
+ argv[argCounter++] = getArg(token);
+ if (argCounter == QUERY_VALUE_MAX_ARGS)
+ break; /* Stop processing args no matter what */
+ }
+
+ /* The value we look for is the first token on the line */
+ if (argv[0] == NULL)
+ return; /* SHOULD NOT HAPPEN */
+ else
+ keyValue = argv[0];
+
+ if ((keyValue[0] == '@') && (_tcslen(keyValue) == 1)) {
+ LONG lLen = KEY_MAX_LEN;
+ TCHAR* lpsData = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,KEY_MAX_LEN);
+ /*
+ * We need to query the key default value
+ */
+ hRes = RegQueryValue(currentKeyHandle, currentKeyName, (LPBYTE)lpsData, &lLen);
+ if (hRes == ERROR_MORE_DATA) {
+ lpsData = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lpsData, lLen);
+ hRes = RegQueryValue(currentKeyHandle, currentKeyName, (LPBYTE)lpsData, &lLen);
+ }
+ if (hRes == ERROR_SUCCESS) {
+ lpsRes = HeapAlloc(GetProcessHeap(), 0, lLen);
+ strncpy(lpsRes, lpsData, lLen);
+ lpsRes[lLen-1]='\0';
+ }
+ } else {
+ DWORD dwLen = KEY_MAX_LEN;
+ BYTE* lpbData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, KEY_MAX_LEN);
+ DWORD dwType;
+ /*
+ * We need to query a specific value for the key
+ */
+ hRes = RegQueryValueEx(
+ currentKeyHandle,
+ keyValue,
+ 0,
+ &dwType,
+ (LPBYTE)lpbData,
+ &dwLen);
+
+ if (hRes == ERROR_MORE_DATA) {
+ lpbData = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lpbData, dwLen * sizeof(TCHAR));
+ hRes = RegQueryValueEx(currentKeyHandle, keyValue, NULL, &dwType, (LPBYTE)lpbData, &dwLen);
+ }
+
+ if (hRes == ERROR_SUCCESS) {
+ /*
+ * Convert the returned data to a displayable format
+ */
+ switch (dwType) {
+ case REG_SZ:
+ case REG_EXPAND_SZ:
+ lpsRes = HeapAlloc(GetProcessHeap(), 0, dwLen * sizeof(TCHAR));
+ strncpy(lpsRes, lpbData, dwLen);
+ lpsRes[dwLen-1] = '\0';
+ break;
+ case REG_DWORD:
+ lpsRes = convertHexToDWORDStr(lpbData, dwLen);
+ break;
+ default:
+ lpsRes = convertHexToHexCSV(lpbData, dwLen);
+ break;
+ }
+ }
+
+ HeapFree(GetProcessHeap(), 0, lpbData);
+ }
+ if (hRes == ERROR_SUCCESS) {
+ _tprintf(_T("Value \"%s\" = \"%s\" in key [%s]\n"), keyValue, lpsRes, currentKeyName);
+
+ } else {
+ _tprintf(_T("ERROR Value \"%s\" not found. for key \"%s\"\n"), keyValue, currentKeyName);
+ }
+
+ /*
+ * Do some cleanup
+ */
+ for (counter=0; counter<argCounter; counter++)
+ if (argv[counter] != NULL)
+ HeapFree(GetProcessHeap(), 0, argv[counter]);
+
+ if (lpsRes != NULL)
+ HeapFree(GetProcessHeap(), 0, lpsRes);
+#endif
+}
+
+/******************************************************************************
+ * Calls command for each line of a registry file.
+ * Correctly processes comments (in # form), line continuation.
+ *
+ * Parameters:
+ * in - input stream to read from
+ * command - command to be called for each line
+ */
+void processRegLines(FILE *in, CommandAPI command)
+{
+ LPTSTR line = NULL; /* line read from input stream */
+ ULONG lineSize = REG_VAL_BUF_SIZE;
+
+ line = HeapAlloc(GetProcessHeap(), 0, lineSize * sizeof(TCHAR));
+ CHECK_ENOUGH_MEMORY(line);
+
+ while (!feof(in)) {
+ LPTSTR s; /* The pointer into line for where the current fgets should read */
+ s = line;
+ for (;;) {
+ size_t size_remaining;
+ int size_to_get;
+ TCHAR *s_eol; /* various local uses */
+
+ /* Do we need to expand the buffer ? */
+ assert (s >= line && s <= line + lineSize);
+ size_remaining = lineSize - (s-line);
+ if (size_remaining < 2) { /* room for 1 character and the \0 */
+ TCHAR *new_buffer;
+ size_t new_size = lineSize + REG_VAL_BUF_SIZE;
+ if (new_size > lineSize) /* no arithmetic overflow */
+ new_buffer = HeapReAlloc (GetProcessHeap(), 0, line, new_size * sizeof(TCHAR));
+ else
+ new_buffer = NULL;
+ CHECK_ENOUGH_MEMORY(new_buffer);
+ line = new_buffer;
+ s = line + lineSize - size_remaining;
+ lineSize = new_size;
+ size_remaining = lineSize - (s-line);
+ }
+
+ /* Get as much as possible into the buffer, terminated either by
+ * eof, error, eol or getting the maximum amount. Abort on error.
+ */
+//
+// This line is surely foobar, don't want to read INT_MAX in buffer at s, it's never going to be that big...
+// size_to_get = (size_remaining > INT_MAX ? INT_MAX : size_remaining);
+//
+// Looks as if 'lineSize' contains the number of characters of buffer size
+//
+ size_to_get = (size_remaining > lineSize ? lineSize : size_remaining);
+
+ if (NULL == _fgetts(s, size_to_get, in)) {
+ if (ferror(in)) {
+ //_tperror(_T("While reading input"));
+ perror ("While reading input");
+ //exit(IO_ERROR);
+ return;
+ } else {
+ assert (feof(in));
+ *s = _T('\0');
+ /* It is not clear to me from the definition that the
+ * contents of the buffer are well defined on detecting
+ * an eof without managing to read anything.
+ */
+ }
+ }
+
+ /* If we didn't read the eol nor the eof go around for the rest */
+ s_eol = _tcschr (s, _T('\n'));
+ if (!feof (in) && !s_eol) {
+ s = _tcschr (s, _T('\0'));
+ /* It should be s + size_to_get - 1 but this is safer */
+ continue;
+ }
+
+ /* If it is a comment line then discard it and go around again */
+ if (line [0] == _T('#')) {
+ s = line;
+ continue;
+ }
+
+ /* Remove any line feed. Leave s_eol on the \0 */
+ if (s_eol) {
+ *s_eol = _T('\0');
+ if (s_eol > line && *(s_eol-1) == _T('\r'))
+ *--s_eol = _T('\0');
+ } else {
+ s_eol = _tcschr (s, _T('\0'));
+ }
+ /* If there is a concatenating \\ then go around again */
+ if (s_eol > line && *(s_eol-1) == _T('\\')) {
+ int c;
+ s = s_eol-1;
+ /* The following error protection could be made more self-
+ * correcting but I thought it not worth trying.
+ */
+
+ if ((c = _fgettc(in)) == _TEOF || c != _T(' ') ||
+ (c = _fgettc(in)) == _TEOF || c != _T(' '))
+ _tprintf(_T("ERROR - invalid continuation.\n"));
+ continue;
+ }
+ break; /* That is the full virtual line */
+ }
+ command(line);
+ }
+ command(NULL);
+ HeapFree(GetProcessHeap(), 0, line);
+}
+
+/******************************************************************************
+ * This funtion is the main entry point to the registerDLL action. It
+ * receives the currently read line, then loads and registers the requested DLLs
+ */
+void doRegisterDLL(LPTSTR stdInput)
+{
+ HMODULE theLib = 0;
+ UINT retVal = 0;
+
+ /* Check for valid input */
+ if (stdInput == NULL) return;
+
+ /* Load and register the library, then free it */
+ theLib = LoadLibrary(stdInput);
+ if (theLib) {
+ FARPROC lpfnDLLRegProc = GetProcAddress(theLib, "DllRegisterServer");
+ if (lpfnDLLRegProc) {
+ retVal = (*lpfnDLLRegProc)();
+ } else {
+ _tprintf(_T("Couldn't find DllRegisterServer proc in '%s'.\n"), stdInput);
+ }
+ if (retVal != S_OK) {
+ _tprintf(_T("Couldn't find DllRegisterServer proc in '%s'.\n"), stdInput);
+ }
+ FreeLibrary(theLib);
+ } else {
+ _tprintf(_T("Could not load DLL '%s'.\n"), stdInput);
+ }
+}
+
+/******************************************************************************
+ * This funtion is the main entry point to the unregisterDLL action. It
+ * receives the currently read line, then loads and unregisters the requested DLLs
+ */
+void doUnregisterDLL(LPTSTR stdInput)
+{
+ HMODULE theLib = 0;
+ UINT retVal = 0;
+
+ /* Check for valid input */
+ if (stdInput == NULL) return;
+
+ /* Load and unregister the library, then free it */
+ theLib = LoadLibrary(stdInput);
+ if (theLib) {
+ FARPROC lpfnDLLRegProc = GetProcAddress(theLib, "DllUnregisterServer");
+ if (lpfnDLLRegProc) {
+ retVal = (*lpfnDLLRegProc)();
+ } else {
+ _tprintf(_T("Couldn't find DllUnregisterServer proc in '%s'.\n"), stdInput);
+ }
+ if (retVal != S_OK) {
+ _tprintf(_T("DLLUnregisterServer error 0x%x in '%s'.\n"), retVal, stdInput);
+ }
+ FreeLibrary(theLib);
+ } else {
+ _tprintf(_T("Could not load DLL '%s'.\n"), stdInput);
+ }
+}
+
+/****************************************************************************
+ * REGPROC_print_error
+ *
+ * Print the message for GetLastError
+ */
+
+void REGPROC_print_error(VOID)
+{
+ LPVOID lpMsgBuf;
+ DWORD error_code;
+ int status;
+
+ error_code = GetLastError ();
+ status = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, error_code, 0, (LPTSTR) &lpMsgBuf, 0, NULL);
+ if (!status) {
+ _tprintf(_T("Cannot display message for error %ld, status %ld\n"), error_code, GetLastError());
+ } else {
+ _tprintf(_T("REGPROC_print_error() - "));
+ puts(lpMsgBuf);
+ LocalFree((HLOCAL)lpMsgBuf);
+ }
+ //exit(1);
+}
+
+/******************************************************************************
+ * Checks whether the buffer has enough room for the string or required size.
+ * Resizes the buffer if necessary.
+ *
+ * Parameters:
+ * buffer - pointer to a buffer for string
+ * len - current length of the buffer in characters.
+ * required_len - length of the string to place to the buffer in characters.
+ * The length does not include the terminating null character.
+ */
+void REGPROC_resize_char_buffer(TCHAR **buffer, DWORD *len, DWORD required_len)
+{
+ required_len++;
+ if (required_len > *len) {
+ *len = required_len;
+ *buffer = HeapReAlloc(GetProcessHeap(), 0, *buffer, *len * sizeof(**buffer));
+ CHECK_ENOUGH_MEMORY(*buffer);
+ }
+}
+
+/******************************************************************************
+ * Prints string str to file
+ */
+void REGPROC_export_string(FILE *file, TCHAR *str)
+{
+ size_t len = _tcslen(str);
+ size_t i;
+
+ /* escaping characters */
+ for (i = 0; i < len; i++) {
+ TCHAR c = str[i];
+ switch (c) {
+ //case _T('\\'): _fputts(_T("\\\\"), file); break;
+ case _T('\"'): _fputts(_T("\\\""), file); break;
+ case _T('\n'): _fputts(_T("\\\n"), file); break;
+ default: _fputtc(c, file); break;
+ }
+ }
+}
+
+/******************************************************************************
+ * Writes contents of the registry key to the specified file stream.
+ *
+ * Parameters:
+ * file - writable file stream to export registry branch to.
+ * key - registry branch to export.
+ * reg_key_name_buf - name of the key with registry class.
+ * Is resized if necessary.
+ * reg_key_name_len - length of the buffer for the registry class in characters.
+ * val_name_buf - buffer for storing value name.
+ * Is resized if necessary.
+ * val_name_len - length of the buffer for storing value names in characters.
+ * val_buf - buffer for storing values while extracting.
+ * Is resized if necessary.
+ * val_size - size of the buffer for storing values in bytes.
+ */
+void export_hkey(FILE *file, HKEY key,
+ TCHAR **reg_key_name_buf, DWORD *reg_key_name_len,
+ TCHAR **val_name_buf, DWORD *val_name_len,
+ BYTE **val_buf, DWORD *val_size)
+{
+ DWORD max_sub_key_len;
+ DWORD max_val_name_len;
+ DWORD max_val_size;
+ DWORD curr_len;
+ DWORD i;
+ BOOL more_data;
+ LONG ret;
+
+ /* get size information and resize the buffers if necessary */
+ if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, &max_sub_key_len, NULL,
+ NULL, &max_val_name_len, &max_val_size, NULL, NULL) != ERROR_SUCCESS) {
+ REGPROC_print_error();
+ }
+ curr_len = _tcslen(*reg_key_name_buf);
+ REGPROC_resize_char_buffer(reg_key_name_buf, reg_key_name_len, max_sub_key_len + curr_len + 1);
+ REGPROC_resize_char_buffer(val_name_buf, val_name_len, max_val_name_len);
+ if (max_val_size > *val_size) {
+ *val_size = max_val_size;
+ *val_buf = HeapReAlloc(GetProcessHeap(), 0, *val_buf, *val_size * sizeof(TCHAR));
+ CHECK_ENOUGH_MEMORY(val_buf);
+ }
+ /* output data for the current key */
+ _fputts(_T("\n["), file);
+ _fputts(*reg_key_name_buf, file);
+ _fputts(_T("]\n"), file);
+ /* print all the values */
+ i = 0;
+ more_data = TRUE;
+ while (more_data) {
+ DWORD value_type;
+ DWORD val_name_len1 = *val_name_len;
+ DWORD val_size1 = *val_size;
+ ret = RegEnumValue(key, i, *val_name_buf, &val_name_len1, NULL, &value_type, *val_buf, &val_size1);
+ if (ret != ERROR_SUCCESS) {
+ more_data = FALSE;
+ if (ret != ERROR_NO_MORE_ITEMS) {
+ REGPROC_print_error();
+ }
+ } else {
+ i++;
+ if ((*val_name_buf)[0]) {
+ _fputts(_T("\""), file);
+ REGPROC_export_string(file, *val_name_buf);
+ _fputts(_T("\"="), file);
+ } else {
+ _fputts(_T("@="), file);
+ }
+ switch (value_type) {
+ case REG_EXPAND_SZ:
+ _fputts(_T("expand:"), file);
+ case REG_SZ:
+ _fputts(_T("\""), file);
+ REGPROC_export_string(file, *val_buf);
+ _fputts(_T("\"\n"), file);
+ break;
+ case REG_DWORD:
+ _ftprintf(file, _T("dword:%08lx\n"), *((DWORD *)*val_buf));
+ break;
+ default:
+/*
+ _tprintf(_T("warning - unsupported registry format '%ld', ") \
+ _T("treating as binary\n"), value_type);
+ _tprintf(_T("key name: \"%s\"\n"), *reg_key_name_buf);
+ _tprintf(_T("value name:\"%s\"\n\n"), *val_name_buf);
+ */
+ /* falls through */
+ case REG_MULTI_SZ:
+ /* falls through */
+ case REG_BINARY:
+ {
+ DWORD i1;
+ TCHAR *hex_prefix;
+ TCHAR buf[20];
+ int cur_pos;
+
+ if (value_type == REG_BINARY) {
+ hex_prefix = _T("hex:");
+ } else {
+ hex_prefix = buf;
+ _stprintf(buf, _T("hex(%ld):"), value_type);
+ }
+ /* position of where the next character will be printed */
+ /* NOTE: yes, _tcslen("hex:") is used even for hex(x): */
+ cur_pos = _tcslen(_T("\"\"=")) + _tcslen(_T("hex:")) +
+ _tcslen(*val_name_buf);
+ _fputts(hex_prefix, file);
+ for (i1 = 0; i1 < val_size1; i1++) {
+ _ftprintf(file, _T("%02x"), (unsigned int)(*val_buf)[i1]);
+ if (i1 + 1 < val_size1) {
+ _fputts(_T(","), file);
+ }
+ cur_pos += 3;
+ /* wrap the line */
+ if (cur_pos > REG_FILE_HEX_LINE_LEN) {
+ _fputts(_T("\\\n "), file);
+ cur_pos = 2;
+ }
+ }
+ _fputts(_T("\n"), file);
+ break;
+ }
+ }
+ }
+ }
+ i = 0;
+ more_data = TRUE;
+ (*reg_key_name_buf)[curr_len] = _T('\\');
+ while (more_data) {
+ DWORD buf_len = *reg_key_name_len - curr_len;
+ ret = RegEnumKeyEx(key, i, *reg_key_name_buf + curr_len + 1, &buf_len, NULL, NULL, NULL, NULL);
+ if (ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) {
+ more_data = FALSE;
+ if (ret != ERROR_NO_MORE_ITEMS) {
+ REGPROC_print_error();
+ }
+ } else {
+ HKEY subkey;
+
+ i++;
+ if (RegOpenKey(key, *reg_key_name_buf + curr_len + 1, &subkey) == ERROR_SUCCESS) {
+ export_hkey(file, subkey, reg_key_name_buf, reg_key_name_len, val_name_buf, val_name_len, val_buf, val_size);
+ RegCloseKey(subkey);
+ } else {
+ REGPROC_print_error();
+ }
+ }
+ }
+ (*reg_key_name_buf)[curr_len] = _T('\0');
+}
+/*
+#define REG_NONE ( 0 ) // No value type
+#define REG_SZ ( 1 ) // Unicode nul terminated string
+#define REG_EXPAND_SZ ( 2 ) // Unicode nul terminated string
+ // (with environment variable references)
+#define REG_BINARY ( 3 ) // Free form binary
+#define REG_DWORD ( 4 ) // 32-bit number
+#define REG_DWORD_LITTLE_ENDIAN ( 4 ) // 32-bit number (same as REG_DWORD)
+#define REG_DWORD_BIG_ENDIAN ( 5 ) // 32-bit number
+#define REG_LINK ( 6 ) // Symbolic Link (unicode)
+#define REG_MULTI_SZ ( 7 ) // Multiple Unicode strings
+#define REG_RESOURCE_LIST ( 8 ) // Resource list in the resource map
+#define REG_FULL_RESOURCE_DESCRIPTOR ( 9 ) // Resource list in the hardware description
+#define REG_RESOURCE_REQUIREMENTS_LIST ( 10 )
+
+ */
+/******************************************************************************
+ * Open file for export.
+ */
+FILE *REGPROC_open_export_file(TCHAR *file_name)
+{
+//_CRTIMP FILE * __cdecl _wfopen(const wchar_t *, const wchar_t *);
+
+//FILE* fopen (const char* szFileName, const char* szMode);
+//FILE* _wfopen(const wchar_t *file, const wchar_t *mode);
+
+ FILE *file = _tfopen(file_name, _T("w"));
+ if (!file) {
+ perror("");
+ _tprintf(_T("REGPROC_open_export_file(%s) - Can't open file.\n"), file_name);
+ //exit(1);
+ return NULL;
+ }
+ _fputts(_T("REGEDIT4\n"), file);
+ return file;
+}
+
+/******************************************************************************
+ * Writes contents of the registry key to the specified file stream.
+ *
+ * Parameters:
+ * file_name - name of a file to export registry branch to.
+ * reg_key_name - registry branch to export. The whole registry is exported if
+ * reg_key_name is NULL or contains an empty string.
+ */
+BOOL export_registry_key(TCHAR* file_name, TCHAR* reg_key_name)
+{
+ HKEY reg_key_class;
+
+ TCHAR *reg_key_name_buf;
+ TCHAR *val_name_buf;
+ BYTE *val_buf;
+ DWORD reg_key_name_len = KEY_MAX_LEN;
+ DWORD val_name_len = KEY_MAX_LEN;
+ DWORD val_size = REG_VAL_BUF_SIZE;
+ FILE *file = NULL;
+
+ //_tprintf(_T("export_registry_key(%s, %s)\n"), reg_key_name, file_name);
+
+ reg_key_name_buf = HeapAlloc(GetProcessHeap(), 0, reg_key_name_len * sizeof(*reg_key_name_buf));
+ val_name_buf = HeapAlloc(GetProcessHeap(), 0, val_name_len * sizeof(*val_name_buf));
+ val_buf = HeapAlloc(GetProcessHeap(), 0, val_size);
+ CHECK_ENOUGH_MEMORY(reg_key_name_buf && val_name_buf && val_buf);
+
+ if (reg_key_name && reg_key_name[0]) {
+ TCHAR *branch_name;
+ HKEY key;
+
+ REGPROC_resize_char_buffer(®_key_name_buf, ®_key_name_len,
+ _tcslen(reg_key_name));
+ _tcscpy(reg_key_name_buf, reg_key_name);
+
+ /* open the specified key */
+ reg_key_class = getRegClass(reg_key_name);
+ if (reg_key_class == (HKEY)ERROR_INVALID_PARAMETER) {
+ _tprintf(_T("Incorrect registry class specification in '%s\n"), reg_key_name);
+ //exit(1);
+ return FALSE;
+ }
+ branch_name = getRegKeyName(reg_key_name);
+ CHECK_ENOUGH_MEMORY(branch_name);
+ if (!branch_name[0]) {
+ /* no branch - registry class is specified */
+ file = REGPROC_open_export_file(file_name);
+ export_hkey(file, reg_key_class,
+ ®_key_name_buf, ®_key_name_len,
+ &val_name_buf, &val_name_len,
+ &val_buf, &val_size);
+ } else if (RegOpenKey(reg_key_class, branch_name, &key) == ERROR_SUCCESS) {
+ file = REGPROC_open_export_file(file_name);
+ export_hkey(file, key,
+ ®_key_name_buf, ®_key_name_len,
+ &val_name_buf, &val_name_len,
+ &val_buf, &val_size);
+ RegCloseKey(key);
+ } else {
+ _tprintf(_T("Can't export. Registry key '%s does not exist!\n"), reg_key_name);
+ REGPROC_print_error();
+ }
+ HeapFree(GetProcessHeap(), 0, branch_name);
+ } else {
+ int i;
+
+ /* export all registry classes */
+ file = REGPROC_open_export_file(file_name);
+ for (i = 0; i < REG_CLASS_NUMBER; i++) {
+ /* do not export HKEY_CLASSES_ROOT */
+ if (reg_class_keys[i] != HKEY_CLASSES_ROOT &&
+ reg_class_keys[i] != HKEY_CURRENT_USER &&
+ reg_class_keys[i] != HKEY_CURRENT_CONFIG) {
+ _tcscpy(reg_key_name_buf, reg_class_names[i]);
+ export_hkey(file, reg_class_keys[i],
+ ®_key_name_buf, ®_key_name_len,
+ &val_name_buf, &val_name_len,
+ &val_buf, &val_size);
+ }
+ }
+ }
+ if (file) {
+ fclose(file);
+ }
+// HeapFree(GetProcessHeap(), 0, reg_key_name);
+ HeapFree(GetProcessHeap(), 0, val_buf);
+ HeapFree(GetProcessHeap(), 0, val_name_buf);
+ HeapFree(GetProcessHeap(), 0, reg_key_name_buf);
+ return TRUE;
+}
+
+/******************************************************************************
+ * Reads contents of the specified file into the registry.
+ */
+BOOL import_registry_file(LPTSTR filename)
+{
+ FILE* reg_file = _tfopen(filename, _T("r"));
+
+ if (reg_file) {
+ processRegLines(reg_file, doSetValue);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/******************************************************************************
+ * Recursive function which removes the registry key with all subkeys.
+ */
+BOOL delete_branch(HKEY key, TCHAR** reg_key_name_buf, DWORD* reg_key_name_len)
+{
+ HKEY branch_key;
+ DWORD max_sub_key_len;
+ DWORD subkeys;
+ DWORD curr_len;
+ LONG ret;
+ long int i;
+
+ if (RegOpenKey(key, *reg_key_name_buf, &branch_key) != ERROR_SUCCESS) {
+ REGPROC_print_error();
+ return FALSE;
+ }
+
+ /* get size information and resize the buffers if necessary */
+ if (RegQueryInfoKey(branch_key, NULL, NULL, NULL, &subkeys, &max_sub_key_len,
+ NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
+ REGPROC_print_error();
+ RegCloseKey(branch_key);
+ return FALSE;
+ }
+ curr_len = _tcslen(*reg_key_name_buf);
+ REGPROC_resize_char_buffer(reg_key_name_buf, reg_key_name_len, max_sub_key_len + curr_len + 1);
+
+ (*reg_key_name_buf)[curr_len] = '\\';
+ for (i = subkeys - 1; i >= 0; i--) {
+ DWORD buf_len = *reg_key_name_len - curr_len;
+ ret = RegEnumKeyEx(branch_key, i, *reg_key_name_buf + curr_len + 1, &buf_len, NULL, NULL, NULL, NULL);
+ if (ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA && ret != ERROR_NO_MORE_ITEMS) {
+ REGPROC_print_error();
+ RegCloseKey(branch_key);
+ return FALSE;
+ } else {
+ delete_branch(key, reg_key_name_buf, reg_key_name_len);
+ }
+ }
+ (*reg_key_name_buf)[curr_len] = '\0';
+ RegCloseKey(branch_key);
+ RegDeleteKey(key, *reg_key_name_buf);
+ return TRUE;
+}
+
+/******************************************************************************
+ * Removes the registry key with all subkeys. Parses full key name.
+ *
+ * Parameters:
+ * reg_key_name - full name of registry branch to delete. Ignored if is NULL,
+ * empty, points to register key class, does not exist.
+ */
+void delete_registry_key(TCHAR* reg_key_name)
+{
+ TCHAR* branch_name;
+ DWORD branch_name_len;
+ HKEY reg_key_class;
+ HKEY branch_key;
+
+ if (!reg_key_name || !reg_key_name[0]) {
+ return;
+ }
+ /* open the specified key */
+ reg_key_class = getRegClass(reg_key_name);
+ if (reg_key_class == (HKEY)ERROR_INVALID_PARAMETER) {
+ _tprintf(_T("Incorrect registry class specification in '%s'\n"), reg_key_name);
+ //exit(1);
+ return;
+ }
+ branch_name = getRegKeyName(reg_key_name);
+ CHECK_ENOUGH_MEMORY(branch_name);
+ branch_name_len = _tcslen(branch_name);
+ if (!branch_name[0]) {
+ _tprintf(_T("Can't delete registry class '%s'\n"), reg_key_name);
+ //exit(1);
+ return;
+ }
+ if (RegOpenKey(reg_key_class, branch_name, &branch_key) == ERROR_SUCCESS) {
+ /* check whether the key exists */
+ RegCloseKey(branch_key);
+ delete_branch(reg_key_class, &branch_name, &branch_name_len);
+ }
+ HeapFree(GetProcessHeap(), 0, branch_name);
+}
+
--- /dev/null
+/*
+ * Copyright 1999 Sylvain St-Germain
+ * Copyright 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
+ */
+
+/******************************************************************************
+ * Defines and consts
+ */
+#define KEY_MAX_LEN 1024
+
+/* Return values */
+#define SUCCESS 0
+#define KEY_VALUE_ALREADY_SET 2
+
+typedef void (*CommandAPI)(LPTSTR lpsLine);
+
+void doSetValue(LPTSTR lpsLine);
+void doDeleteValue(LPTSTR lpsLine);
+void doCreateKey(LPTSTR lpsLine);
+void doDeleteKey(LPTSTR lpsLine);
+void doQueryValue(LPTSTR lpsLine);
+void doRegisterDLL(LPTSTR lpsLine);
+void doUnregisterDLL(LPTSTR lpsLine);
+
+BOOL export_registry_key(TCHAR* file_name, TCHAR* reg_key_name);
+BOOL import_registry_file(LPTSTR filename);
+void delete_registry_key(TCHAR* reg_key_name);
+
+void processRegLines(FILE* in, CommandAPI command);
+
+/*
+ * Generic prototypes
+ */
+#ifdef _UNICODE
+#define get_file_name get_file_nameW
+#else
+#define get_file_name get_file_nameA
+#endif
+
+char* getToken(char** str, const char* delims);
+void get_file_nameA(CHAR** command_line, CHAR* filename, int max_filename);
+void get_file_nameW(CHAR** command_line, WCHAR* filename, int max_filename);
+DWORD convertHexToDWord(TCHAR* str, BYTE* buf);
+DWORD convertHexCSVToHex(TCHAR* str, BYTE* buf, ULONG bufLen);
+LPTSTR convertHexToHexCSV(BYTE* buf, ULONG len);
+LPTSTR convertHexToDWORDStr(BYTE* buf, ULONG len);
+LPTSTR getRegKeyName(LPTSTR lpLine);
+HKEY getRegClass(LPTSTR lpLine);
+DWORD getDataType(LPTSTR* lpValue, DWORD* parse_type);
+LPTSTR getArg(LPTSTR arg);
+HRESULT openKey(LPTSTR stdInput);
+void closeKey(VOID);
+
+/*
+ * api setValue prototypes
+ */
+void processSetValue(LPTSTR cmdline);
+HRESULT setValue(LPTSTR val_name, LPTSTR val_data);
+
+/*
+ * api queryValue prototypes
+ */
+void processQueryValue(LPTSTR cmdline);
+
+#ifdef __GNUC__
+#ifdef WIN32_REGDBG
+//typedef UINT_PTR SIZE_T, *PSIZE_T;
+//#define _MAX_PATH 260 /* max. length of full pathname */
+#endif /*WIN32_REGDBG*/
+
+#ifdef UNICODE
+#define _tfopen _wfopen
+#else
+#define _tfopen fopen
+#endif
+
+#endif /*__GNUC__*/
+
+LPVOID RegHeapAlloc(
+ HANDLE hHeap, // handle to private heap block
+ DWORD dwFlags, // heap allocation control
+ SIZE_T dwBytes // number of bytes to allocate
+);
+
+LPVOID RegHeapReAlloc(
+ HANDLE hHeap, // handle to heap block
+ DWORD dwFlags, // heap reallocation options
+ LPVOID lpMem, // pointer to memory to reallocate
+ SIZE_T dwBytes // number of bytes to reallocate
+);
+
+BOOL RegHeapFree(
+ HANDLE hHeap, // handle to heap
+ DWORD dwFlags, // heap free options
+ LPVOID lpMem // pointer to memory
+);
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.sym
+*.exe
+*.dsp
+*.dsw
--- /dev/null
+*.exe
+*.o
+*.sym
--- /dev/null
+*.exe
+*.sym
--- /dev/null
+*.sym
+*.exe
+*.o
--- /dev/null
+*.exe
+*.o
+*.sym
--- /dev/null
+*.exe
+*.sym
+*.o
--- /dev/null
+*.exe
+*.o
+*.sym
--- /dev/null
+*.exe
+*.o
+*.sym
--- /dev/null
+*.o
+*.exe
+*.sym
--- /dev/null
+*.o
+*.exe
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+winhello.exe
+winhello.nostrip.exe
+winhello.sym
+winhello.coff
+*.d
+*.o
\ No newline at end of file
--- /dev/null
+
+// ------------------------------------------------------------------
+// Windows 2000 Graphics API Black Book
+// Chapter 1 - Listing 1.1 (WM_PAINT Demo)
+//
+// Created by Damon Chandler <dmc27@ee.cornell.edu>
+// Updates can be downloaded at: <www.coriolis.com>
+//
+// Please do not hesistate to e-mail me at dmc27@ee.cornell.edu
+// if you have any questions about this code.
+// ------------------------------------------------------------------
+
+
+//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+#include <windows.h>
+//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+
+const char* WndClassName = "GMainWnd";
+LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam,
+ LPARAM LParam);
+
+
+int APIENTRY WinMain(HINSTANCE HInstance, HINSTANCE HPrevInstance,
+ LPTSTR lpCmdLine, int nCmdShow)
+{
+ WNDCLASS wc;
+ memset(&wc, 0, sizeof(WNDCLASS));
+
+ wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
+ wc.lpfnWndProc = MainWndProc;
+ wc.hInstance = HInstance;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground =
+ reinterpret_cast<HBRUSH>(COLOR_BTNFACE + 1);
+ wc.lpszClassName = WndClassName;
+
+ if (RegisterClass(&wc))
+ {
+ HWND HWnd =
+ CreateWindow(WndClassName, TEXT("WM_PAINT Demo"),
+ WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_VISIBLE,
+ CW_USEDEFAULT, CW_USEDEFAULT, 200, 150,
+ NULL, NULL, HInstance, NULL);
+
+ if (HWnd)
+ {
+ ShowWindow(HWnd, nCmdShow);
+ UpdateWindow(HWnd);
+
+ MSG msg;
+ while (GetMessage(&msg, NULL, 0, 0))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ }
+ return 0;
+}
+//------------------------------------------------------------------
+
+
+LRESULT CALLBACK MainWndProc(HWND HWnd, UINT Msg, WPARAM WParam,
+ LPARAM LParam)
+{
+ switch (Msg)
+ {
+ case WM_PAINT:
+ {
+ // determine the invalidated area of the window
+ RECT RUpdate;
+ GetUpdateRect(HWnd, &RUpdate, false);
+
+ // grab a handle to our window's
+ // common display device context
+ HDC Hdc = GetDC(HWnd);
+#if 0
+ try
+#endif
+ {
+ RECT RClient;
+ GetClientRect(HWnd, &RClient);
+
+ // set the clipping region
+ IntersectClipRect(Hdc, RUpdate.left, RUpdate.top,
+ RUpdate.right, RUpdate.bottom);
+
+ // fill the client area with the background brush
+ HBRUSH HBrush =
+ reinterpret_cast<HBRUSH>(
+ GetClassLong(HWnd, GCL_HBRBACKGROUND)
+ );
+ FillRect(Hdc, &RClient, HBrush);
+
+ // render the persistent text
+ const char* text = "Persistent Text";
+ SetTextColor(Hdc, PALETTERGB(0, 0, 255));
+ DrawText(Hdc, text, strlen(text), &RClient,
+ DT_CENTER | DT_VCENTER | DT_SINGLELINE);
+ }
+#if 0
+ catch (...)
+#endif
+ {
+ // release the device context
+ ReleaseDC(HWnd, Hdc);
+
+ // validate the update area
+ ValidateRect(HWnd, &RUpdate);
+ }
+ // release the device context
+ ReleaseDC(HWnd, Hdc);
+
+ // validate the update area
+ ValidateRect(HWnd, &RUpdate);
+
+ break;
+ }
+ case WM_DESTROY:
+ {
+ PostQuitMessage(0);
+ return 0;
+ }
+ }
+ return DefWindowProc(HWnd, Msg, WParam, LParam);
+}
+//------------------------------------------------------------------
+
--- /dev/null
+# Makefile - Proj_Listing1_1.dsp
+
+ifndef CFG
+CFG=Proj_Listing1_1 - Win32 Debug
+endif
+CC=gcc
+CFLAGS=
+CXX=g++
+CXXFLAGS=$(CFLAGS)
+RC=windres -O COFF
+ifeq "$(CFG)" "Proj_Listing1_1 - Win32 Release"
+CFLAGS+=-fexceptions -O2 -DWIN32 -DNDEBUG -D_WINDOWS -D_MBCS -W
+LD=$(CXX) $(CXXFLAGS)
+LDFLAGS=
+LDFLAGS+=-Wl,--subsystem,windows
+LIBS+=-lkernel32 -luser32 -lgdi32
+else
+ifeq "$(CFG)" "Proj_Listing1_1 - Win32 Debug"
+CFLAGS+=-fexceptions -g -O0 -DWIN32 -D_DEBUG -D_WINDOWS -D_MBCS -W
+LD=$(CXX) $(CXXFLAGS)
+LDFLAGS=
+LDFLAGS+=-Wl,--subsystem,windows
+LIBS+=-lkernel32 -luser32 -lgdi32
+endif
+endif
+
+ifndef TARGET
+TARGET=WM_PAINT.exe
+endif
+
+.PHONY: all
+all: $(TARGET)
+
+%.o: %.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
+
+%.o: %.cpp
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ -c $<
+
+%.res: %.rc
+ $(RC) $(CPPFLAGS) -o $@ -i $<
+
+SOURCE_FILES= \
+ Listing1_1.cpp
+
+HEADER_FILES=
+
+RESOURCE_FILES=
+
+SRCS=$(SOURCE_FILES) $(HEADER_FILES) $(RESOURCE_FILES)
+
+OBJS=$(patsubst %.rc,%.res,$(patsubst %.cpp,%.o,$(patsubst %.c,%.o,$(filter %.c %.cpp %.rc,$(SRCS)))))
+
+$(TARGET): $(OBJS)
+ $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+
+.PHONY: clean
+clean:
+ -del $(OBJS) $(TARGET)
+
+.PHONY: depends
+depends:
+ -$(CXX) $(CXXFLAGS) $(CPPFLAGS) -MM $(filter %.c %.cpp,$(SRCS)) > Proj_Listing1_1.dep
+
+-include Proj_Listing1_1.dep
+
--- /dev/null
+#
+# ReactOS system testsets makefile
+#
+
+PATH_TO_TOP = ../..
+
+include $(PATH_TO_TOP)/rules.mak
+
+
+# Testset applications
+TEST_SETS = loadlib
+
+TEST_KERNEL32 =
+
+TEST_MSVCRT =
+
+TEST_COM =
+
+TEST_SEH =
+
+TEST_REGRESSIONS =
+
+all: $(TEST_SETS) $(TEST_KERNEL32) $(TEST_MSVCRT) $(TEST_COM) $(TEST_SEH) $(TEST_REGRESSIONS)
+
+depends:
+
+implib: $(TEST_SETS:%=%_implib) \
+ $(TEST_KERNEL32:%=%_implib) \
+ $(TEST_MSVCRT:%=%_implib) \
+ $(TEST_COM:%=%_implib) \
+ $(TEST_SEH:%=%_implib) \
+ $(TEST_REGRESSIONS:%=%_implib)
+
+clean: $(TEST_SETS:%=%_clean) \
+ $(TEST_KERNEL32:%=%_clean) \
+ $(TEST_MSVCRT:%=%_clean) \
+ $(TEST_COM:%=%_clean) \
+ $(TEST_SEH:%=%_clean) \
+ $(TEST_REGRESSIONS:%=%_clean)
+
+install: $(TEST_SETS:%=%_install) \
+ $(TEST_KERNEL32:%=%_install) \
+ $(TEST_MSVCRT:%=%_install) \
+ $(TEST_COM:%=%_install) \
+ $(TEST_SEH:%=%_install) \
+ $(TEST_REGRESSIONS:%=%_install)
+
+dist: $(TEST_SETS:%=%_dist) \
+ $(TEST_KERNEL32:%=%_dist) \
+ $(TEST_MSVCRT:%=%_dist) \
+ $(TEST_COM:%=%_dist) \
+ $(TEST_SEH:%=%_dist) \
+ $(TEST_REGRESSIONS:%=%_dist)
+
+.PHONY: all depends implib clean install dist
+
+
+#
+# Testset Applications
+#
+$(TEST_SETS): %:
+ make -C $*
+
+$(TEST_SETS:%=%_implib): %_implib:
+ make -C $* implib
+
+$(TEST_SETS:%=%_clean): %_clean:
+ make -C $* clean
+
+$(TEST_SETS:%=%_dist): %_dist:
+ make -C $* dist
+
+$(TEST_SETS:%=%_install): %_install:
+ make -C $* install
+
+.PHONY: $(TEST_SETS) $(TEST_SETS:%=%_implib) $(TEST_SETS:%=%_clean) $(TEST_SETS:%=%_install) $(TEST_SETS:%=%_dist)
+
+
+#
+# Kernel32 Test Applications
+#
+$(TEST_KERNEL32): %:
+ make -C kernel32/$*
+
+$(TEST_KERNEL32:%=%_implib): %_implib:
+ make -C kernel32/$* implib
+
+$(TEST_KERNEL32:%=%_clean): %_clean:
+ make -C kernel32/$* clean
+
+$(TEST_KERNEL32:%=%_dist): %_dist:
+ make -C kernel32/$* dist
+
+$(TEST_KERNEL32:%=%_install): %_install:
+ make -C kernel32/$* install
+
+.PHONY: $(TEST_KERNEL32) $(TEST_KERNEL32:%=%_implib) $(TEST_KERNEL32:%=%_clean) $(TEST_KERNEL32:%=%_install) $(TEST_KERNEL32:%=%_dist)
+
+
+#
+# msvcrt Test Applications
+#
+$(TEST_MSVCRT): %:
+ make -C msvcrt/$*
+
+$(TEST_MSVCRT:%=%_implib): %_implib:
+ make -C msvcrt/$* implib
+
+$(TEST_MSVCRT:%=%_clean): %_clean:
+ make -C msvcrt/$* clean
+
+$(TEST_MSVCRT:%=%_dist): %_dist:
+ make -C msvcrt/$* dist
+
+$(TEST_MSVCRT:%=%_install): %_install:
+ make -C msvcrt/$* install
+
+.PHONY: $(TEST_MSVCRT) $(TEST_MSVCRT:%=%_implib) $(TEST_MSVCRT:%=%_clean) $(TEST_MSVCRT:%=%_install) $(TEST_MSVCRT:%=%_dist)
+
+
+#
+# COM Test Applications
+#
+$(TEST_COM): %:
+ make -C com/$*
+
+$(TEST_COM:%=%_implib): %_implib:
+ make -C com/$* implib
+
+$(TEST_COM:%=%_clean): %_clean:
+ make -C com/$* clean
+
+$(TEST_COM:%=%_dist): %_dist:
+ make -C com/$* dist
+
+$(TEST_COM:%=%_install): %_install:
+ make -C com/$* install
+
+.PHONY: $(TEST_COM) $(TEST_COM:%=%_implib) $(TEST_COM:%=%_clean) $(TEST_COM:%=%_install) $(TEST_COM:%=%_dist)
+
+
+#
+# SEH Test Applications
+#
+$(TEST_SEH): %:
+ make -C seh/$*
+
+$(TEST_SEH:%=%_implib): %_implib:
+ make -C seh/$* implib
+
+$(TEST_SEH:%=%_clean): %_clean:
+ make -C seh/$* clean
+
+$(TEST_SEH:%=%_dist): %_dist:
+ make -C seh/$* dist
+
+$(TEST_SEH:%=%_install): %_install:
+ make -C seh/$* install
+
+.PHONY: $(TEST_SEH) $(TEST_SEH:%=%_implib) $(TEST_SEH:%=%_clean) $(TEST_SEH:%=%_install) $(TEST_SEH:%=%_dist)
+
+
+#
+# Regression Test Applications
+#
+$(TEST_REGRESSIONS): %:
+ make -C regres/$*
+
+$(TEST_REGRESSIONS:%=%_implib): %_implib:
+ make -C regres/$* implib
+
+$(TEST_REGRESSIONS:%=%_clean): %_clean:
+ make -C regres/$* clean
+
+$(TEST_REGRESSIONS:%=%_dist): %_dist:
+ make -C regres/$* dist
+
+$(TEST_REGRESSIONS:%=%_install): %_install:
+ make -C regres/$* install
+
+.PHONY: $(TEST_REGRESSIONS) $(TEST_REGRESSIONS:%=%_implib) $(TEST_REGRESSIONS:%=%_clean) $(TEST_REGRESSIONS:%=%_install) $(TEST_REGRESSIONS:%=%_dist)
+
+
+etags:
+ find . -name "*.[ch]" -print | etags --language=c -
+
+# EOF
+
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
+*.dsp
+*.dsw
+*.ncb
+*.opt
--- /dev/null
+/*
+ * ReactOS test program -
+ *
+ * loadlib.c
+ *
+ * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <windows.h>
+#include "loadlib.h"
+
+
+#define APP_VERSION 1
+#define MAX_LIBS 25
+
+#ifdef UNICODE
+#define TARGET "UNICODE"
+BOOL bUseAnsi = FALSE;
+#else
+#define TARGET "MBCS"
+BOOL bUseAnsi = TRUE;
+#endif
+BOOL verbose_flagged = FALSE;
+BOOL debug_flagged = FALSE;
+BOOL loop_flagged = FALSE;
+BOOL recursive_flagged = FALSE;
+
+HANDLE OutputHandle;
+HANDLE InputHandle;
+
+
+void dprintf(char* fmt, ...)
+{
+ va_list args;
+ char buffer[255];
+
+ va_start(args, fmt);
+ wvsprintfA(buffer, fmt, args);
+ WriteConsoleA(OutputHandle, buffer, lstrlenA(buffer), NULL, NULL);
+ va_end(args);
+}
+
+long getinput(char* buf, int buflen)
+{
+ DWORD result;
+
+ ReadConsoleA(InputHandle, buf, buflen, &result, NULL);
+ return (long)result;
+}
+
+DWORD ReportLastError(void)
+{
+ DWORD dwError = GetLastError();
+ if (dwError != ERROR_SUCCESS) {
+ PSTR msg = NULL;
+ if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+ 0, dwError, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (PSTR)&msg, 0, NULL)) {
+ if (msg != NULL) {
+ dprintf("ReportLastError() %d - %s\n", dwError, msg);
+ } else {
+ dprintf("ERROR: ReportLastError() %d - returned TRUE but with no msg string!\n", dwError);
+ }
+ } else {
+ dprintf("ReportLastError() %d - unknown error\n", dwError);
+ }
+ if (msg != NULL) {
+ LocalFree(msg);
+ }
+ }
+ return dwError;
+}
+
+const char* appName(const char* argv0)
+{
+ const char* name;
+
+ name = (const char*)strrchr(argv0, '\\');
+ if (name != NULL)
+ return name + 1;
+ return argv0;
+}
+
+int usage(const char* appName)
+{
+ dprintf("USAGE: %s libname [libname ...] [unicode]|[ansi] [loop][recurse]\n", appName);
+ dprintf("\tWhere libname(s) is one or more libraries to load.\n");
+ dprintf("\t[unicode] - perform tests using UNICODE api calls\n");
+ dprintf("\t[ansi] - perform tests using ANSI api calls\n");
+ dprintf("\t default is %s\n", TARGET);
+ dprintf("\t[loop] - run test process in continuous loop\n");
+ dprintf("\t[recurse] - load libraries recursively rather than sequentually\n");
+ dprintf("\t[debug] - enable debug mode (unused)\n");
+ dprintf("\t[verbose] - enable verbose output (unused)\n");
+ return 0;
+}
+
+DWORD LoadLibraryList(char** libnames, int counter, BOOL bUseAnsi)
+{
+ HMODULE hModule;
+
+ dprintf("Attempting to LoadLibrary");
+ if (bUseAnsi) {
+ dprintf("A(%s) - ", *libnames);
+ hModule = LoadLibraryA(*libnames);
+ } else {
+ int len;
+ wchar_t libnameW[500];
+ len = mbstowcs(libnameW, *libnames, strlen(*libnames));
+ if (len) {
+ libnameW[len] = L'\0';
+ dprintf("W(%S) - ", libnameW);
+ hModule = LoadLibraryW(libnameW);
+ } else {
+ return ERROR_INVALID_PARAMETER;
+ }
+ }
+ if (hModule == NULL) {
+ dprintf("\nERROR: failed to obtain handle to module %s - %x\n", *libnames, hModule);
+ return ReportLastError();
+ }
+ dprintf("%x\n", hModule);
+
+ if (counter--) {
+ LoadLibraryList(++libnames, counter, bUseAnsi);
+ }
+
+ if (!FreeLibrary(hModule)) {
+ dprintf("ERROR: failed to free module %s - %x\n", *libnames, hModule);
+ return ReportLastError();
+ } else {
+ dprintf("FreeLibrary(%x) - successfull.\n", hModule);
+ }
+ return 0L;
+}
+
+int __cdecl main(int argc, char* argv[])
+{
+ char* libs[MAX_LIBS];
+ int lib_count = 0;
+ int test_num = 0;
+ int result = 0;
+ int i = 0;
+
+ AllocConsole();
+ InputHandle = GetStdHandle(STD_INPUT_HANDLE);
+ OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
+
+ dprintf("%s application - build %03d (default: %s)\n", appName(argv[0]), APP_VERSION, TARGET);
+ if (argc < 2) {
+ /*return */usage(appName(argv[0]));
+ }
+ memset(libs, 0, sizeof(libs));
+ for (i = 1; i < argc; i++) {
+ if (lstrcmpiA(argv[i], "ansi") == 0) {
+ bUseAnsi = TRUE;
+ } else if (lstrcmpiA(argv[i], "unicode") == 0) {
+ bUseAnsi = FALSE;
+ } else if (lstrcmpiA(argv[i], "loop") == 0) {
+ loop_flagged = 1;
+ } else if (lstrcmpiA(argv[i], "recurse") == 0) {
+ recursive_flagged = 1;
+ } else if (lstrcmpiA(argv[i], "verbose") == 0) {
+ verbose_flagged = 1;
+ } else if (lstrcmpiA(argv[i], "debug") == 0) {
+ debug_flagged = 1;
+ } else {
+ if (lib_count < MAX_LIBS) {
+ libs[lib_count] = argv[i];
+ ++lib_count;
+ }
+ }
+ }
+ if (lib_count) {
+ do {
+ if (recursive_flagged) {
+ result = LoadLibraryList(libs, lib_count - 1, bUseAnsi);
+ } else {
+ for (i = 0; i < lib_count; i++) {
+ result = LoadLibraryList(&libs[i], 0, bUseAnsi);
+ //if (result != 0) break;
+ }
+ }
+ } while (loop_flagged);
+ } else {
+ int len;
+ char buffer[500];
+ do {
+ dprintf("\nEnter library name to attempt loading: ");
+ len = getinput(buffer, sizeof(buffer) - 1);
+ if (len > 2) {
+ char* buf = buffer;
+ buffer[len-2] = '\0';
+ result = LoadLibraryList(&buf, 0, bUseAnsi);
+ } else break;
+ } while (!result && len);
+ }
+ dprintf("finished\n");
+ return result;
+}
+
+
+#ifdef _NOCRT
+char* args[] = { "loadlib.exe", "advapi32.dll", "user32.dll", "recurse"};
+int __cdecl mainCRTStartup(void)
+{
+ return main(3, args);
+}
+#endif /*__GNUC__*/
--- /dev/null
+/*
+ * ReactOS test program -
+ *
+ * loadlib.h
+ *
+ * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __LOADLIB_H__
+#define __LOADLIB_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern BOOL verbose_flagged;
+extern BOOL debug_flagged;
+extern BOOL loop_flagged;
+extern BOOL recursive_flagged;
+
+DWORD ReportLastError(void);
+long getinput(char* Buffer, int buflen);
+void dprintf(char* fmt, ...);
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // __LOADLIB_H__
--- /dev/null
+#
+# $Id: makefile,v 1.0
+
+PATH_TO_TOP = ../../..
+
+TARGET_NORC = yes
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = console
+
+TARGET_NAME = loadlib
+
+#TARGET_CFLAGS = -DDBG -DUNICODE -D_UNICODE
+
+TARGET_SDKLIBS = kernel32.a ntdll.a
+
+TARGET_OBJECTS = $(TARGET_NAME).o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+/*
+ * ReactOS test program -
+ *
+ * _tfileio.c
+ *
+ * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <tchar.h>
+#include <wchar.h>
+#include <stdio.h>
+
+
+#ifdef UNICODE
+#define _tfopen _wfopen
+#define _tunlink _wunlink
+#define _TEOF WEOF
+#define _gettchar getwchar
+#define _puttchar putwchar
+#define _THEX_FORMAT _T("0x%04x ")
+#else /*UNICODE*/
+#define _tfopen fopen
+#define _tunlink _unlink
+#define _TEOF EOF
+#define _gettchar getchar
+#define _puttchar putchar
+#define _THEX_FORMAT "0x%02x "
+#endif /*UNICODE*/
+
+
+#define TEST_BUFFER_SIZE 200
+#define TEST_FILE_LINES 4
+
+extern BOOL verbose_flagged;
+extern BOOL status_flagged;
+
+static TCHAR test_buffer[TEST_BUFFER_SIZE];
+
+static TCHAR dos_data[] = _T("line1: this is a bunch of readable text.\r\n")\
+ _T("line2: some more printable text and punctuation !@#$%^&*()\r\n")\
+ _T("line3: followed up with some numerals 1234567890\r\n")\
+ _T("line4: done.\r\n");
+
+static TCHAR nix_data[] = _T("line1: this is a bunch of readable text.\n")\
+ _T("line2: some more printable text and punctuation !@#$%^&*()\n")\
+ _T("line3: followed up with some numerals 1234567890\n")\
+ _T("line4: done.\n");
+
+#ifdef UNICODE
+#define TEST_B1_FILE_SIZE ((((sizeof(dos_data)/2)-1)+TEST_FILE_LINES)/2) // (166+4)/2=85
+#define TEST_B2_FILE_SIZE (((sizeof(dos_data)/2)-1)*2) // (166*2) =332
+#define TEST_B3_FILE_SIZE ((((sizeof(nix_data)/2)-1)+TEST_FILE_LINES)/2) // (162+4)/2=83
+#define TEST_B4_FILE_SIZE (((sizeof(nix_data)/2)-1)*2) // (162*2) =324
+#else /*UNICODE*/
+#define TEST_B1_FILE_SIZE (sizeof(dos_data)-1+TEST_FILE_LINES) // (166+4)=170
+#define TEST_B2_FILE_SIZE (sizeof(dos_data)-1-TEST_FILE_LINES) // (166-4)=162
+#define TEST_B3_FILE_SIZE (sizeof(nix_data)-1+TEST_FILE_LINES) // (162+4)=166
+#define TEST_B4_FILE_SIZE (sizeof(nix_data)-1) // (162) =162
+#endif /*UNICODE*/
+
+
+// result = create_test_file(file_name, _T("wb"), _T("rb"), file_data);
+
+static BOOL test_file_truncate(TCHAR* file_name)
+{
+ BOOL result = FALSE;
+ int count = -1;
+ int error_code;
+ TCHAR ch;
+ TCHAR* file_data = _T("this file should have been truncated to zero bytes...");
+ FILE *file = _tfopen(file_name, _T("wb"));
+
+ if (verbose_flagged) {
+ _tprintf(_T("test_file_truncate(\"%s\")\n"), file_name);
+ }
+
+ if (file != NULL) {
+ if (_fputts(file_data, file) != _TEOF) {
+ } else {
+ _tprintf(_T("ERROR: failed to write data to file \"%s\"\n"), file_name);
+ _tprintf(_T("ERROR: ferror returned %d\n"), ferror(file));
+ }
+ fclose(file);
+ } else {
+ _tprintf(_T("ERROR: failed to open/create file \"%s\" for output\n"), file_name);
+ _tprintf(_T("ERROR: ferror returned %d\n"), ferror(file));
+ }
+
+ file = _tfopen(file_name, _T("wb"));
+ if (file != NULL) {
+ error_code = ferror(file);
+ if (error_code) {
+ _tprintf(_T("ERROR: (%s) ferror returned %d\n"), file_name, error_code);
+ }
+ fclose(file);
+ } else {
+ _tprintf(_T("ERROR: (%s) failed to open file for truncating\n"), file_name);
+ }
+
+ file = _tfopen(file_name, _T("rb"));
+ if (file != NULL) {
+ count = 0;
+ while ((ch = _fgettc(file)) != _TEOF) {
+ if (verbose_flagged) {
+ _tprintf(_THEX_FORMAT, ch);
+ }
+ ++count;
+ }
+ error_code = ferror(file);
+ if (error_code) {
+ _tprintf(_T("ERROR: (%s) ferror returned %d after reading\n"), file_name, error_code);
+ perror("Read error");
+ }
+ fclose(file);
+ } else {
+ _tprintf(_T("ERROR: (%s) failed to open file for reading\n"), file_name);
+ }
+ if (count) {
+ result = TRUE;
+ }
+ return result;
+}
+
+static BOOL create_output_file(TCHAR* file_name, TCHAR* file_mode, TCHAR* file_data)
+{
+ BOOL result = FALSE;
+ FILE *file = _tfopen(file_name, file_mode);
+ if (file != NULL) {
+ if (_fputts(file_data, file) != _TEOF) {
+ result = TRUE;
+ } else {
+ _tprintf(_T("ERROR: failed to write data to file \"%s\"\n"), file_name);
+ _tprintf(_T("ERROR: ferror returned %d\n"), ferror(file));
+ }
+ fclose(file);
+ } else {
+ _tprintf(_T("ERROR: failed to open/create file \"%s\" for output\n"), file_name);
+ _tprintf(_T("ERROR: ferror returned %d\n"), ferror(file));
+ }
+ return result;
+}
+
+static BOOL verify_output_file(TCHAR* file_name, TCHAR* file_mode, TCHAR* file_data)
+{
+ int error_code;
+ int offset = 0;
+ int line_num = 0;
+ BOOL result = FALSE;
+ BOOL error_flagged = FALSE;
+ FILE* file = _tfopen(file_name, file_mode);
+ if (file == NULL) {
+ _tprintf(_T("ERROR: (%s) Can't open file for reading\n"), file_name);
+ _tprintf(_T("ERROR: ferror returned %d\n"), ferror(file));
+ return FALSE;
+ } else if (status_flagged) {
+ _tprintf(_T("STATUS: (%s) opened file for reading\n"), file_name);
+ }
+ while (_fgetts(test_buffer, TEST_BUFFER_SIZE, file)) {
+ int length = _tcslen(test_buffer);
+ int req_len = _tcschr(file_data+offset, _T('\n')) - (file_data+offset) + 1;
+
+ ++line_num;
+ if (length > req_len) {
+ _tprintf(_T("ERROR: read excess bytes from line %d, length %d, but expected %d\n"), line_num, length, req_len);
+ error_flagged = TRUE;
+ break;
+ }
+ if (length < req_len) {
+ _tprintf(_T("ERROR: read to few bytes from line %d, length %d, but expected %d\n"), line_num, length, req_len);
+ error_flagged = TRUE;
+ break;
+ }
+ if (status_flagged) {
+ _tprintf(_T("STATUS: Verifying %d bytes read from line %d\n"), length, line_num);
+ }
+ if (_tcsncmp(test_buffer, file_data+offset, length - 1) == 0) {
+ result = TRUE;
+ } else {
+ if (status_flagged) {
+ int i;
+ _tprintf(_T("WARNING: (%s) failed to verify file\n"), file_name);
+ for (i = 0; i < length; i++) {
+ if (file_data[offset+i] != test_buffer[i]) {
+ _tprintf(_T("line %d, offset %d expected: 0x%04x found: 0x%04x\n"), line_num, i, (int)file_data[offset+i], (int)test_buffer[i]);
+ }
+ }
+ _tprintf(_T("\n"));
+ } else {
+ error_flagged = TRUE;
+ }
+ }
+ offset += length;
+ }
+ error_code = ferror(file);
+ if (error_code) {
+ _tprintf(_T("ERROR: (%s) ferror returned %d after reading\n"), file_name, error_code);
+ perror("Read error");
+ }
+ if (!line_num) {
+ _tprintf(_T("ERROR: (%s) failed to read from file\n"), file_name);
+ }
+ if (error_flagged == TRUE) {
+ _tprintf(_T("ERROR: (%s) failed to verify file\n"), file_name);
+ result = FALSE;
+ }
+ fclose(file);
+ return result;
+}
+
+static int create_test_file(TCHAR* file_name, TCHAR* write_mode, TCHAR* read_mode, TCHAR* file_data)
+{
+ if (status_flagged) {
+ _tprintf(_T("STATUS: Attempting to create output file %s\n"), file_name);
+ }
+ if (create_output_file(file_name, write_mode, file_data)) {
+ if (status_flagged) {
+ _tprintf(_T("STATUS: Attempting to verify output file %s\n"), file_name);
+ }
+ if (verify_output_file(file_name, read_mode, file_data)) {
+ if (status_flagged) {
+ _tprintf(_T("SUCCESS: %s verified ok\n"), file_name);
+ }
+ } else {
+ //_tprintf(_T("ERROR: failed to verify file %s\n"), file_name);
+ return 2;
+ }
+ } else {
+ _tprintf(_T("ERROR: failed to create file %s\n"), file_name);
+ return 1;
+ }
+ return 0;
+}
+
+static int check_file_size(TCHAR* file_name, TCHAR* file_mode, int expected)
+{
+ int count = 0;
+ FILE* file;
+ TCHAR ch;
+ int error_code;
+
+ if (status_flagged) {
+ //_tprintf(_T("STATUS: (%s) checking for %d bytes in %s mode\n"), file_name, expected, _tcschr(file_mode, _T('b')) ? _T("binary") : _T("text"));
+ _tprintf(_T("STATUS: (%s) checking for %d bytes with mode %s\n"), file_name, expected, file_mode);
+ }
+ file = _tfopen(file_name, file_mode);
+ if (file == NULL) {
+ _tprintf(_T("ERROR: (%s) failed to open file for reading\n"), file_name);
+ return 1;
+ }
+ while ((ch = _fgettc(file)) != _TEOF) {
+ if (verbose_flagged) {
+ _tprintf(_THEX_FORMAT, ch);
+ }
+ ++count;
+ }
+ error_code = ferror(file);
+ if (error_code) {
+ _tprintf(_T("ERROR: (%s) ferror returned %d after reading\n"), file_name, error_code);
+ perror("Read error");
+ }
+
+ if (verbose_flagged) {
+// _puttc(_T('\n'), stdout);
+ }
+ fclose(file);
+ if (count == expected) {
+ if (status_flagged) {
+ _tprintf(_T("PASSED: (%s) read %d bytes\n"), file_name, count);
+ }
+ } else {
+ _tprintf(_T("FAILED: (%s) read %d bytes but expected %d using mode \"%s\"\n"), file_name, count, expected, file_mode);
+ }
+ return (count == expected) ? 0 : -1;
+}
+
+static int test_console_io(void)
+{
+ TCHAR buffer[81];
+ TCHAR ch;
+ int i, j;
+
+ _tprintf(_T("Enter a line for echoing:\n"));
+
+ //for (i = 0; (i < 80) && ((ch = _gettchar()) != _TEOF) && (ch != _T('\n')); i++) {
+ for (i = 0; (i < 80) && ((ch = _gettc(stdin)) != _TEOF) && (ch != _T('\n')); i++) {
+ buffer[i] = (TCHAR)ch;
+ }
+ buffer[i] = _T('\0');
+ for (j = 0; j < i; j++) {
+ _puttc(buffer[j], stdout);
+ }
+ _puttc(_T('\n'), stdout);
+ _tprintf(_T("%s\n"), buffer);
+ return 0;
+}
+
+static int test_console_getchar(void)
+{
+ int result = 0;
+ TCHAR ch;
+
+ _tprintf(_T("Enter lines for dumping or <ctrl-z><nl> to finish:\n"));
+
+ //while ((ch = _gettchar()) != _TEOF) {
+ while ((ch = _gettc(stdin)) != _TEOF) {
+ _tprintf(_THEX_FORMAT, ch);
+ //printf("0x%04x ", ch);
+ }
+ return result;
+}
+
+static int test_console_putch(void)
+{
+ int result = 0;
+
+ _putch('1');
+ _putch('@');
+ _putch('3');
+ _putch(':');
+ _putch('\n');
+ _putch('a');
+ _putch('B');
+ _putch('c');
+ _putch(':');
+ _putch('\n');
+ return result;
+}
+
+static int test_unlink_files(void)
+{
+ int result = 0;
+
+ //printf("sizeof dos_data: %d\n", sizeof(dos_data));
+ //printf("sizeof nix_data: %d\n", sizeof(nix_data));
+
+ result |= _tunlink(_T("binary.dos"));
+ result |= _tunlink(_T("binary.nix"));
+ result |= _tunlink(_T("text.dos"));
+ result |= _tunlink(_T("text.nix"));
+ return result;
+}
+
+static int test_text_fileio(TCHAR* file_name, TCHAR* file_data, int tsize, int bsize)
+{
+ int result = 0;
+
+ result = create_test_file(file_name, _T("w"), _T("r"), file_data);
+ result = check_file_size(file_name, _T("r"), tsize);
+ result = check_file_size(file_name, _T("rb"), bsize);
+ return result;
+}
+
+static int test_binary_fileio(TCHAR* file_name, TCHAR* file_data, int tsize, int bsize)
+{
+ int result = 0;
+
+ result = create_test_file(file_name, _T("wb"), _T("rb"), file_data);
+ result = check_file_size(file_name, _T("r"), tsize);
+ result = check_file_size(file_name, _T("rb"), bsize);
+ return result;
+}
+
+static int test_files(int test_num, char* type)
+{
+ int result = 0;
+
+ printf("performing test: %d (%s)\n", test_num, type);
+
+
+ if (test_file_truncate(_T("zerosize.foo"))) {
+ printf("System unable to truncate files yet, unlinking:\n");
+ test_unlink_files();
+ }
+
+ switch (test_num) {
+ case 1:
+ result = test_text_fileio(_T("text.dos"), dos_data, 166, TEST_B1_FILE_SIZE);
+ break;
+ case 2:
+ result = test_binary_fileio(_T("binary.dos"), dos_data, TEST_B2_FILE_SIZE, 166);
+ break;
+ case 3:
+ result = test_text_fileio(_T("text.nix"), nix_data, 162, TEST_B3_FILE_SIZE);
+ break;
+ case 4:
+ result = test_binary_fileio(_T("binary.nix"), nix_data, TEST_B4_FILE_SIZE, 162);
+ break;
+ case 5:
+ result = test_console_io();
+ break;
+ case 6:
+ result = test_console_getchar();
+ break;
+ case 7:
+ result = test_console_putch();
+ break;
+ case -1:
+ result = test_unlink_files();
+ break;
+ default:
+ _tprintf(_T("no test number selected\n"));
+ break;
+ }
+ return result;
+}
--- /dev/null
+/*
+ * ReactOS test program -
+ *
+ * _fileio.c
+ *
+ * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#undef UNICODE
+#undef _UNICODE
+#include "_tfileio.c"
+
+
+int run_ansi_tests(int test_num)
+{
+ return test_files(test_num, "ANSI");
+}
--- /dev/null
+/*
+ * ReactOS test program -
+ *
+ * main.c
+ *
+ * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <tchar.h>
+#include <wchar.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "main.h"
+
+
+#define VERSION 1
+
+#ifdef UNICODE
+#define TARGET "UNICODE"
+#else
+#define TARGET "MBCS"
+#endif
+
+BOOL verbose_flagged = 0;
+BOOL status_flagged = 0;
+
+int usage(char* argv0)
+{
+ printf("USAGE: %s test_id [unicode]|[ansi] [clean]|[status][verbose]\n", argv0);
+ printf("\tWhere test_id is one of:\n");
+ printf("\t0 - (default) regression mode, run tests 1-4 displaying failures only\n");
+ printf("\t1 - Write DOS style eol data to file in text mode (text.dos)\n");
+ printf("\t2 - Write NIX style eol data to file in binary mode (binary.dos)\n");
+ printf("\t3 - Write DOS style eol data to file in text mode (text.nix)\n");
+ printf("\t4 - Write NIX style eol data to file in binary mode (binary.nix)\n");
+ printf("\t5 - Echo console line input\n");
+ printf("\t6 - Dump console line input in hex format\n");
+ printf("\t7 - The source code is your friend\n");
+ printf("\t[unicode] - perform tests using UNICODE versions of library functions\n");
+ printf("\t[ansi] - perform tests using ANSI versions of library functions\n");
+ printf("\t If neither unicode or ansi is specified build default is used\n");
+ printf("\t[clean] - delete all temporary test output files\n");
+ printf("\t[status] - enable extra status display while running\n");
+ printf("\t[verbose] - enable verbose output when running\n");
+ return 0;
+}
+
+int __cdecl main(int argc, char* argv[])
+{
+ int test_num = 0;
+ int version = 0;
+ int result = 0;
+ int i = 0;
+
+ printf("%s test application - build %03d (default: %s)\n", argv[0], VERSION, TARGET);
+ if (argc < 2) {
+ return usage(argv[0]);
+ }
+ for (i = 1; i < argc; i++) {
+ if (strstr(argv[i], "ansi") || strstr(argv[i], "ANSI")) {
+ version = 1;
+ } else if (strstr(argv[i], "unicode") || strstr(argv[i], "UNICODE")) {
+ version = 2;
+ } else if (strstr(argv[i], "clean") || strstr(argv[i], "CLEAN")) {
+ test_num = -1;
+ } else if (strstr(argv[i], "verbose") || strstr(argv[i], "VERBOSE")) {
+ verbose_flagged = 1;
+ } else if (strstr(argv[i], "status") || strstr(argv[i], "STATUS")) {
+ status_flagged = 1;
+ } else {
+ test_num = atoi(argv[1]);
+ //if (test_num < 0
+ }
+ }
+ for (i = test_num; i <= test_num; i++) {
+ if (!test_num) {
+ test_num = 4;
+ i = 1;
+ }
+ switch (version) {
+ case 1:
+ result = run_ansi_tests(i);
+ break;
+ case 2:
+ result = run_unicode_tests(i);
+ break;
+ default:
+ result = run_ansi_tests(i);
+ result = run_unicode_tests(i);
+ break;
+ }
+ }
+ printf("finished\n");
+ return result;
+}
+
+#ifndef __GNUC__
+
+char* args[] = { "fileio.exe", "0", "unicode", "verbose"};
+
+int __cdecl mainCRTStartup(void)
+{
+ main(2, args);
+ return 0;
+}
+
+#endif /*__GNUC__*/
--- /dev/null
+/*
+ * ReactOS test program -
+ *
+ * main.h
+ *
+ * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __MAIN_H__
+#define __MAIN_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+int app_main(int argc, char* argv[]);
+DWORD GetInput(char* Buffer, int buflen);
+
+int test_ansi_files(int test_num);
+int test_unicode_files(int test_num);
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // __MAIN_H__
--- /dev/null
+#
+# $Id: makefile,v 1.0
+
+PATH_TO_TOP = ../../../..
+
+TEST_ROOT = $(PATH_TO_TOP)/apps/testsets/test
+
+TARGET_NORC = yes
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = console
+
+TARGET_NAME = fileio
+
+#TARGET_CFLAGS = -I$(TEST_ROOT) -DDBG -DUNICODE -D_UNICODE
+TARGET_CFLAGS = -I$(TEST_ROOT) -DDBG
+
+TARGET_SDKLIBS = ntdll.a kernel32.a
+
+TARGET_OBJECTS = $(TARGET_NAME).o wfileio.o main.o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
--- /dev/null
+/*
+ * ReactOS test program -
+ *
+ * wfileio.c
+ *
+ * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define UNICODE
+#define _UNICODE
+#include "_tfileio.c"
+
+
+int run_unicode_tests(int test_num)
+{
+ return test_files(test_num, "UNICODE");
+}
--- /dev/null
+#
+# ReactOS system utilities makefile
+#
+
+PATH_TO_TOP = ../..
+
+include $(PATH_TO_TOP)/rules.mak
+
+
+# Console system utilities
+# cabman cat net objdir partinfo pice ps sc stats
+UTIL_APPS = cat objdir partinfo sc stats tickcount
+
+UTIL_NET_APPS =
+
+
+all: $(UTIL_APPS) $(UTIL_NET_APPS)
+
+depends:
+
+implib: $(UTIL_APPS:%=%_implib) \
+ $(UTIL_NET_APPS:%=%_implib)
+
+clean: $(UTIL_APPS:%=%_clean) \
+ $(UTIL_NET_APPS:%=%_clean)
+
+install: $(UTIL_APPS:%=%_install) \
+ $(UTIL_NET_APPS:%=%_install)
+
+dist: $(UTIL_APPS:%=%_dist) \
+ $(UTIL_NET_APPS:%=%_dist)
+
+.PHONY: all depends implib clean install dist
+
+
+#
+# Utility Applications
+#
+$(UTIL_APPS): %:
+ make -C $*
+
+$(UTIL_APPS:%=%_implib): %_implib:
+ make -C $* implib
+
+$(UTIL_APPS:%=%_clean): %_clean:
+ make -C $* clean
+
+$(UTIL_APPS:%=%_dist): %_dist:
+ make -C $* dist
+
+$(UTIL_APPS:%=%_install): %_install:
+ make -C $* install
+
+.PHONY: $(UTIL_APPS) $(UTIL_APPS:%=%_implib) $(UTIL_APPS:%=%_clean) $(UTIL_APPS:%=%_install) $(UTIL_APPS:%=%_dist)
+
+
+#
+# GUI Utility Applications
+#
+$(UTIL_NET_APPS): %:
+ make -C net/$*
+
+$(UTIL_NET_APPS:%=%_implib): %_implib:
+ make -C net/$* implib
+
+$(UTIL_NET_APPS:%=%_clean): %_clean:
+ make -C net/$* clean
+
+$(UTIL_NET_APPS:%=%_dist): %_dist:
+ make -C net/$* dist
+
+$(UTIL_NET_APPS:%=%_install): %_install:
+ make -C net/$* install
+
+.PHONY: $(UTIL_NET_APPS) $(UTIL_NET_APPS:%=%_implib) $(UTIL_NET_APPS:%=%_clean) $(UTIL_NET_APPS:%=%_install) $(UTIL_NET_APPS:%=%_dist)
+
+
+etags:
+ find . -name "*.[ch]" -print | etags --language=c -
+
+# EOF
+
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+/* $Id$
+ *
+ * ReactOS ps - process list console viewer
+ *
+ * ps.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <windows.h>
+#include <tlhelp32.h>
+
+static char* title = " PID PARENT TIME NAME\n";
+char buf[256];
+
+int main()
+{
+ DWORD r;
+ HANDLE pl;
+ PROCESSENTRY32 pe;
+ HANDLE stdout = GetStdHandle(STD_OUTPUT_HANDLE);
+
+ WriteFile(stdout, title, lstrlen(title), &r, NULL);
+ pl = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ pe.dwSize = sizeof(PROCESSENTRY32);
+ pe.th32ParentProcessID = 0;
+
+ if (Process32First(pl, &pe)) do {
+ int hour;
+ int minute;
+ WORD fatdate;
+ WORD fattime;
+ HANDLE p = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe.th32ProcessID);
+ FILETIME cr;
+ FILETIME ex;
+ FILETIME kt;
+ FILETIME ut;
+ GetProcessTimes(p, &cr, &ex, &kt, &ut);
+ FileTimeToDosDateTime(&cr, &fatdate, &fattime);
+ hour = (fattime & 0xf800) >> 11;
+ minute = (fattime & 0x07e0) >> 5;
+ wsprintf(buf,"%08X %08X %2d:%02d %s\n", pe.th32ProcessID, pe.th32ParentProcessID, hour, minute, pe.szExeFile);
+ WriteFile(stdout, buf, lstrlen(buf), &r, NULL);
+ CloseHandle(p);
+ pe.th32ParentProcessID = 0;
+ } while (Process32Next(pl, &pe));
+
+ CloseHandle(pl);
+}
+/*
+WINBOOL
+STDCALL
+FileTimeToDosDateTime(
+ CONST FILETIME *lpFileTime,
+ LPWORD lpFatDate,
+ LPWORD lpFatTime
+ );
+ */
--- /dev/null
+*.o
+*.d
+sc.exe
+sc.nostrip.exe
+sc.coff
+sc.sym
+sc.map
--- /dev/null
+/*
+ * ReactOS SC - service control console program
+ *
+ * command.c
+ *
+ * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <windows.h>
+#include <wchar.h>
+#include <tchar.h>
+#include "main.h"
+
+
+int sc_Lock(SC_HANDLE hSCManager)
+{
+ dprintf("sc_Lock(%x) - not implemented.\n", hSCManager);
+ return 0;
+}
+
+int sc_QueryLock(SC_HANDLE hSCManager)
+{
+ QUERY_SERVICE_LOCK_STATUS LockStatus;
+ DWORD cbBufSize = sizeof(QUERY_SERVICE_LOCK_STATUS);
+ DWORD cbBytesNeeded;
+
+ dprintf("sc_QueryLock() - called.\n");
+
+ if (QueryServiceLockStatus(hSCManager, &LockStatus, cbBufSize, &cbBytesNeeded)) {
+
+ } else {
+ dprintf("Failed to Query Service Lock Status.\n");
+ ReportLastError();
+ }
+
+ if (!CloseServiceHandle(hSCManager)) {
+ dprintf("Failed to CLOSE handle to SCM.\n");
+ ReportLastError();
+ }
+
+ return 0;
+}
+
+int sc_control(SC_HANDLE hSCManager, char* service, DWORD dwControl)
+{
+ int ret = 0;
+ SC_HANDLE schService;
+ SERVICE_STATUS serviceStatus;
+
+ dprintf("sc_control(%x, %s, %d) - called.\n", hSCManager, service, dwControl);
+
+ schService = OpenServiceA(hSCManager, service, SERVICE_ALL_ACCESS);
+ if (schService != NULL) {
+ ret = ControlService(schService, dwControl, &serviceStatus);
+ dprintf("ControlService(%x, %x, %x) returned %d\n", schService, dwControl, &serviceStatus, ret);
+ if (!ret) {
+
+
+ }
+ CloseServiceHandle(schService);
+ }
+ return ret;
+}
+
+int sc_command(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[])
+{
+// dprintf("sc_command(%x, %d, %s) - called.\n", hSCManager, sc_cmd, argv[]);
+ switch (sc_cmd) {
+ case SC_CMD_START:
+ //return sc_control(hSCManager, sc_cmd_arg, SERVICE_CONTROL_START);
+ dprintf(" - not implemented.\n");
+ break;
+ case SC_CMD_PAUSE:
+ return sc_control(hSCManager, argv[0], SERVICE_CONTROL_PAUSE);
+ case SC_CMD_INTERROGATE:
+ return sc_control(hSCManager, argv[0], SERVICE_CONTROL_INTERROGATE);
+ case SC_CMD_CONTINUE:
+ return sc_control(hSCManager, argv[0], SERVICE_CONTROL_CONTINUE);
+ case SC_CMD_STOP:
+ return sc_control(hSCManager, argv[0], SERVICE_CONTROL_STOP);
+
+// case SC_CMD_CONFIG:
+// case SC_CMD_DESCRIPTION:
+// case SC_CMD_CONTROL:
+
+ case SC_CMD_LOCK:
+ return sc_Lock(hSCManager);
+ case SC_CMD_QUERYLOCK:
+ return sc_QueryLock(hSCManager);
+ default:
+ dprintf("sc_command(%x, %d, %s) - unknown command.\n", hSCManager, sc_cmd, argv[0]);
+ break;
+ }
+ return 0;
+}
--- /dev/null
+/*
+ * ReactOS SC - service control console program
+ *
+ * config.c
+ *
+ * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <windows.h>
+#include <wchar.h>
+#include <tchar.h>
+#include "main.h"
+
+
+int sc_config(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[])
+{
+ dprintf("sc_config(%x, %d, %s) - called.\n", hSCManager, sc_cmd, argv[0]);
+
+ switch (sc_cmd) {
+ case SC_CMD_CONFIG:
+ case SC_CMD_DESCRIPTION:
+ case SC_CMD_FAILURE:
+ case SC_CMD_SDSHOW:
+ case SC_CMD_SDSET:
+ dprintf(" - not implemented.\n");
+ break;
+ default:
+ dprintf("sc_config(%x, %d, %s) - unknown command.\n", hSCManager, sc_cmd, argv[0]);
+ break;
+ }
+ return 0;
+}
+/*
+ switch (sc_cmd) {
+ case SC_CMD_QUERY:
+ case SC_CMD_QUERYEX:
+ case SC_CMD_START:
+ case SC_CMD_PAUSE:
+ case SC_CMD_INTERROGATE:
+ case SC_CMD_CONTINUE:
+ case SC_CMD_STOP:
+ case SC_CMD_CONFIG:
+ case SC_CMD_DESCRIPTION:
+ case SC_CMD_FAILURE:
+ case SC_CMD_QC:
+ case SC_CMD_QDESCRIPTION:
+ case SC_CMD_QFAILURE:
+ case SC_CMD_DELETE:
+ case SC_CMD_CREATE:
+ case SC_CMD_CONTROL:
+ case SC_CMD_SDSHOW:
+ case SC_CMD_SDSET:
+ case SC_CMD_GETDISPLAYNAME:
+ case SC_CMD_GETKEYNAME:
+ case SC_CMD_ENUMDEPEND:
+ case SC_CMD_BOOT:
+ case SC_CMD_LOCK:
+ case SC_CMD_QUERYLOCK:
+ break;
+ }
+ */
--- /dev/null
+/*
+ * ReactOS SC - service control console program
+ *
+ * main.c
+ *
+ * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <windows.h>
+#include <tchar.h>
+#include "main.h"
+
+
+#define VERSION 1
+
+#ifdef UNICODE
+#define TARGET "UNICODE"
+#else
+#define TARGET "MBCS"
+#endif
+
+BOOL verbose_flagged = 0;
+BOOL status_flagged = 0;
+
+HANDLE OutputHandle;
+HANDLE InputHandle;
+
+
+void dprintf(char* fmt, ...)
+{
+ va_list args;
+ char buffer[255];
+
+ va_start(args, fmt);
+ wvsprintfA(buffer, fmt, args);
+ WriteConsoleA(OutputHandle, buffer, lstrlenA(buffer), NULL, NULL);
+ va_end(args);
+}
+
+long getinput(char* buf, int buflen)
+{
+ DWORD result;
+
+ ReadConsoleA(InputHandle, buf, buflen, &result, NULL);
+ return (long)result;
+}
+
+DWORD ReportLastError(void)
+{
+ DWORD dwError = GetLastError();
+ if (dwError != ERROR_SUCCESS) {
+ PTSTR msg = NULL;
+ if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+ 0, dwError, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (PTSTR)&msg, 0, NULL)) {
+ if (msg != NULL) {
+ dprintf("ReportLastError() %d - %s\n", dwError, msg);
+ } else {
+ dprintf("ERROR: ReportLastError() %d - returned TRUE but with no msg string!\n", dwError);
+ }
+ } else {
+ dprintf("ReportLastError() %d - unknown error\n", dwError);
+ }
+ if (msg != NULL) {
+ LocalFree(msg);
+ }
+ }
+ return dwError;
+}
+
+int usage(char* argv0)
+{
+ dprintf("DESCRIPTION:\n");
+ dprintf("\tSC is a command line program used for communicating with\n");
+ dprintf("\tthe Service Control Manager and its services.\n");
+ dprintf("USAGE:\n");
+ dprintf("\tsc <server> [command] [service name] <option1> <option2>...\n");
+
+ dprintf("\tThe optional parameter <server> has the form \"\\ServerName\"\n");
+ dprintf("\tFurther help on commands can be obtained by typing: \"sc [command]\"\n");
+ dprintf("\tService Commands:\n");
+ dprintf("\t query : Queries the status for a service, or\n");
+ dprintf("\t enumerates the status for types of services.\n");
+ dprintf("\t queryex : Queries the extended status for a service, or\n");
+ dprintf("\t enumerates the status for types of services.\n");
+ dprintf("\t start : Starts a service.\n");
+ dprintf("\t pause : Sends a PAUSE control request to a service.\n");
+ dprintf("\t interrogate : Sends a INTERROGATE control request to a service.\n");
+ dprintf("\t continue : Sends a CONTINUE control request to a service.\n");
+ dprintf("\t stop : Sends a STOP request to a service.\n");
+ dprintf("\t config : Changes the configuration of a service (persistant).\n");
+ dprintf("\t description : Changes the description of a service.\n");
+ dprintf("\t failure : Changes the actions taken by a service upon failure.\n");
+ dprintf("\t qc : Queries the configuration information for a service.\n");
+ dprintf("\t qdescription : Queries the description for a service.\n");
+ dprintf("\t qfailure : Queries the actions taken by a service upon failure.\n");
+ dprintf("\t delete : Deletes a service (from the registry).\n");
+ dprintf("\t create : Creates a service. (adds it to the registry).\n");
+ dprintf("\t control : Sends a control to a service.\n");
+// dprintf("\t sdshow : Displays a service's security descriptor.\n");
+// dprintf("\t sdset : Sets a service's security descriptor.\n");
+ dprintf("\t GetDisplayName : Gets the DisplayName for a service.\n");
+ dprintf("\t GetKeyName : Gets the ServiceKeyName for a service.\n");
+ dprintf("\t EnumDepend : Enumerates Service Dependencies.\n");
+ dprintf("\n");
+ dprintf("\tService Name Independant Commands:\n");
+ dprintf("\t boot : (ok | bad) Indicates whether the last boot should\n");
+ dprintf("\t be saved as the last-known-good boot configuration\n");
+ dprintf("\t Lock : Locks the SCM Database\n");
+ dprintf("\t QueryLock : Queries the LockStatus for the SCM Database\n");
+
+ return 0;
+}
+
+
+typedef int (*sc_cmd_proc)(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[]);
+
+typedef struct {
+ SC_CMDS sc_cmd;
+ const char* cmd_str;
+ sc_cmd_proc funcptr;
+ DWORD dwDesiredAccess;
+} sc_cmd_entry;
+
+sc_cmd_entry sc_cmds_table[] = {
+ { SC_CMD_QUERY, "query", sc_query, SC_MANAGER_ALL_ACCESS },
+ { SC_CMD_QUERYEX, "queryex", sc_query, SC_MANAGER_ALL_ACCESS },
+ { SC_CMD_START, "start", sc_command, 0L },
+ { SC_CMD_PAUSE, "pause", sc_command, 0L },
+ { SC_CMD_INTERROGATE, "interrogate", sc_command, 0L },
+ { SC_CMD_CONTINUE, "continue", sc_command, 0L },
+ { SC_CMD_STOP, "stop", sc_command, 0L },
+ { SC_CMD_CONFIG, "config", sc_setup, 0L },
+ { SC_CMD_DESCRIPTION, "description", sc_setup, 0L },
+ { SC_CMD_FAILURE, "failure", sc_setup, 0L },
+ { SC_CMD_QC, "qc", sc_query, 0L },
+ { SC_CMD_QDESCRIPTION, "qdescription", sc_query, 0L },
+ { SC_CMD_QFAILURE, "qfailure", sc_query, 0L },
+ { SC_CMD_DELETE, "delete", sc_setup, 0L },
+ { SC_CMD_CREATE, "create", sc_setup, 0L },
+ { SC_CMD_CONTROL, "control", sc_setup, 0L },
+ { SC_CMD_SDSHOW, "sdshow", sc_query, 0L },
+ { SC_CMD_SDSET, "sdset", sc_setup, 0L },
+ { SC_CMD_GETDISPLAYNAME, "GetDisplayName", sc_query, 0L },
+ { SC_CMD_GETKEYNAME, "GetKeyName", sc_query, 0L },
+ { SC_CMD_ENUMDEPEND, "EnumDepend", sc_query, 0L },
+ { SC_CMD_BOOT, "boot", sc_config, 0L },
+ { SC_CMD_LOCK, "Lock", sc_config, 0L },
+ { SC_CMD_QUERYLOCK, "QueryLock", sc_config, 0L }
+};
+
+
+int sc_main(const sc_cmd_entry* cmd_entry,
+ const char* sc_machine_name,
+ char* sc_cmd_arg[])
+{
+ int result = 1;
+ SC_HANDLE hSCManager;
+ DWORD dwDesiredAccess;
+
+ dprintf("sc_main(%s) - called.\n", cmd_entry->cmd_str);
+ if (sc_machine_name) {
+ dprintf("remote service control not yet implemented.\n");
+ return 2;
+ }
+ dwDesiredAccess = cmd_entry->dwDesiredAccess;
+ if (!dwDesiredAccess) dwDesiredAccess = SC_MANAGER_CONNECT + GENERIC_READ;
+
+ hSCManager = OpenSCManagerA(sc_machine_name, NULL, dwDesiredAccess);
+ //hSCManager = OpenSCManagerW(NULL, NULL, dwDesiredAccess);
+ if (hSCManager != NULL) {
+ result = cmd_entry->funcptr(hSCManager, cmd_entry->sc_cmd, sc_cmd_arg);
+ if (!CloseServiceHandle(hSCManager)) {
+ dprintf("Failed to CLOSE handle to SCM.\n");
+ ReportLastError();
+ }
+ } else {
+ dprintf("Failed to open Service Control Manager.\n");
+ ReportLastError();
+ }
+ return result;
+}
+
+
+int __cdecl main(int argc, char* argv[])
+{
+ int i;
+ const char* sc_machine_name = NULL;
+ const char* sc_cmd_str = argv[1];
+ char** sc_cmd_arg = NULL;
+
+ AllocConsole();
+ InputHandle = GetStdHandle(STD_INPUT_HANDLE);
+ OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
+
+ dprintf("%s application - build %03d (default: %s)\n", argv[0], VERSION, TARGET);
+ if (argc < 2) {
+ return usage(argv[0]);
+ }
+
+ if ((argv[1][0] == '\\') && (argv[1][1] == '\\')) {
+ if (argc < 3) {
+ return usage(argv[0]);
+ }
+ sc_machine_name = argv[1];
+ sc_cmd_str = argv[2];
+ sc_cmd_arg = &argv[3];
+ } else {
+ sc_machine_name = NULL;
+ sc_cmd_str = argv[1];
+ sc_cmd_arg = &argv[2];
+ }
+
+ for (i = 0; i < sizeof(sc_cmds_table)/sizeof(sc_cmd_entry); i++) {
+ sc_cmd_entry* cmd_entry = &(sc_cmds_table[i]);
+ if (lstrcmpiA(sc_cmd_str, cmd_entry->cmd_str) == 0) {
+ return sc_main(cmd_entry, sc_machine_name, sc_cmd_arg);
+ }
+ }
+ return usage(argv[0]);
+}
+
+
+#ifdef _NOCRT
+
+//char* args[] = { "sc.exe", "pause", "smplserv" };
+char* args[] = { "sc.exe", "EnumDepend", "" };
+
+int __cdecl mainCRTStartup(void)
+{
+ main(3, args);
+ return 0;
+}
+
+#endif /*_NOCRT*/
--- /dev/null
+/*
+ * ReactOS test program -
+ *
+ * main.h
+ *
+ * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __MAIN_H__
+#define __MAIN_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+DWORD ReportLastError(void);
+long getinput(char* Buffer, int buflen);
+void dprintf(char* fmt, ...);
+
+typedef enum tag_SC_CMDS {
+ SC_CMD_QUERY,
+ SC_CMD_QUERYEX,
+ SC_CMD_START,
+ SC_CMD_PAUSE,
+ SC_CMD_INTERROGATE,
+ SC_CMD_CONTINUE,
+ SC_CMD_STOP,
+ SC_CMD_CONFIG,
+ SC_CMD_DESCRIPTION,
+ SC_CMD_FAILURE,
+ SC_CMD_QC,
+ SC_CMD_QDESCRIPTION,
+ SC_CMD_QFAILURE,
+ SC_CMD_DELETE,
+ SC_CMD_CREATE,
+ SC_CMD_CONTROL,
+ SC_CMD_SDSHOW,
+ SC_CMD_SDSET,
+ SC_CMD_GETDISPLAYNAME,
+ SC_CMD_GETKEYNAME,
+ SC_CMD_ENUMDEPEND,
+ SC_CMD_BOOT,
+ SC_CMD_LOCK,
+ SC_CMD_QUERYLOCK
+} SC_CMDS;
+
+int sc_query(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[]);
+int sc_setup(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[]);
+int sc_config(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[]);
+int sc_command(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[]);
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // __MAIN_H__
--- /dev/null
+#
+# $Id: makefile,v 1.0
+
+PATH_TO_TOP = ../../..
+
+TARGET_NORC = yes
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = console
+
+TARGET_NAME = sc
+
+TARGET_CFLAGS = -DDBG
+
+TARGET_SDKLIBS = kernel32.a ntdll.a advapi32.a
+
+TARGET_OBJECTS = command.o config.o main.o query.o setup.o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
--- /dev/null
+/*
+ * ReactOS SC - service control console program
+ *
+ * query.c
+ *
+ * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <windows.h>
+#include <wchar.h>
+#include <tchar.h>
+#include "main.h"
+
+
+
+int DisplayServiceInfo(BOOL display_ex)
+{
+ const char* type_str = "WIN32_SHARE_PROCESS";
+ const char* state_str = "RUNNING";
+ const char* flags_str = "RUNS_IN_SYSTEM_PROCESS";
+ const char* features_str = "NOT_STOPABLE,NOT_PAUSABLE,IGNORES_SHUTDOWN";
+
+ const char* ServiceName = "none";
+ const char* DisplayName = "none";
+ int Type;
+ int State;
+ int Win32ExitCode;
+ int ServiceExitCode;
+ int CheckPoint;
+ int WaitHint;
+ int Pid;
+ int Flags;
+
+ Type = 20;
+ State = 4;
+ Win32ExitCode = 0;
+ ServiceExitCode = 0;
+ CheckPoint = 0;
+ WaitHint = 0;
+ Pid = 0;
+ Flags = 0;
+
+ dprintf("\nSERVICE_NAME: %s\n", ServiceName);
+ dprintf("DISPLAY_NAME: %s\n", DisplayName);
+ dprintf("\tTYPE : %d %s\n", Type, type_str);
+ dprintf("\tSTATE : %d %s\n", State, state_str);
+ dprintf("\t : (%s)\n", features_str);
+ dprintf("\tWIN32_EXIT_CODE : %d (0x%01x)\n", Win32ExitCode, Win32ExitCode);
+ dprintf("\tSERVICE_EXIT_CODE : %d (0x%01x)\n", ServiceExitCode, ServiceExitCode);
+ dprintf("\tCHECKPOINT : 0x%01x\n", CheckPoint);
+ dprintf("\tWAIT_HINT : 0x%01x\n", WaitHint);
+
+ if (display_ex) {
+ dprintf("\tPID : %d\n", Pid);
+ dprintf("\tFLAGS : %s\n", flags_str);
+ }
+
+ return 0;
+}
+
+int EnumServicesInfo(void)
+{
+ int entriesRead = 0;
+ int resumeIndex = 0;
+
+ dprintf("Enum: entriesRead = %d\n", entriesRead);
+ dprintf("Enum: resumeIndex = %d\n", resumeIndex);
+
+ DisplayServiceInfo(1);
+
+ return 0;
+}
+
+int sc_query(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[])
+{
+ switch (sc_cmd) {
+ case SC_CMD_QUERY:
+ case SC_CMD_QUERYEX:
+ case SC_CMD_QC:
+ case SC_CMD_QDESCRIPTION:
+ case SC_CMD_QFAILURE:
+ case SC_CMD_SDSHOW:
+ case SC_CMD_GETDISPLAYNAME:
+ case SC_CMD_GETKEYNAME:
+ dprintf("sc_query(%x, %d, %s) - command not implemented.\n", hSCManager, sc_cmd, argv[0]);
+ break;
+ case SC_CMD_ENUMDEPEND:
+ return EnumServicesInfo();
+// case SC_CMD_QUERYLOCK:
+// return sc_QueryLock(hSCManager);
+ default:
+ dprintf("sc_query(%x, %d, %s) - unknown command.\n", hSCManager, sc_cmd, argv[0]);
+ break;
+ }
+ return 0;
+}
+
--- /dev/null
+/*
+ * ReactOS SC - service control console program
+ *
+ * setup.c
+ *
+ * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <windows.h>
+#include <wchar.h>
+#include <tchar.h>
+#include "main.h"
+
+int sc_delete(char* argv[])
+{
+ dprintf("sc_delete(%s) - not implemented.\n", argv[0]);
+ return 0;
+}
+
+int sc_boot(char* arg)
+{
+ dprintf("sc_boot(%s) - not implemented.\n", arg);
+ return 0;
+}
+
+int sc_setup(SC_HANDLE hSCManager, SC_CMDS sc_cmd, char* argv[])
+{
+ dprintf("sc_setup(%x, %d, %s) - called.\n", hSCManager, sc_cmd, argv[0]);
+
+ switch (sc_cmd) {
+// case SC_CMD_DESCRIPTION:
+// case SC_CMD_FAILURE:
+ case SC_CMD_DELETE:
+ return sc_delete(argv);
+ case SC_CMD_CREATE:
+ dprintf(" - not implemented.\n");
+ break;
+// case SC_CMD_SDSHOW:
+// case SC_CMD_SDSET:
+ case SC_CMD_BOOT:
+ return sc_boot(argv[0]);
+ default:
+ dprintf("sc_setup(%x, %d, %s) - unknown command.\n", hSCManager, sc_cmd, argv[0]);
+ break;
+ }
+ return 0;
+}
+
--- /dev/null
+*.o
+*.d
+*.exe
+*.coff
+*.sym
--- /dev/null
+PATH_TO_TOP = ../../..
+
+TARGET_NORC = yes
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = console
+
+TARGET_NAME = tickcount
+
+TARGET_SDKLIBS = kernel32.a
+
+TARGET_OBJECTS = tickcount.o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
--- /dev/null
+/* $Id$
+*/
+/*
+ tickcount -- Display the kernel tick count in human-readable format
+
+ This is public domain software
+*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <tchar.h>
+#include <windows.h>
+
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+
+#define TICKS_YEAR (TICKS_DAY * ((uint64_t)365))
+#define TICKS_MONTH (TICKS_DAY * ((uint64_t)30))
+#define TICKS_WEEK (TICKS_DAY * ((uint64_t)7))
+#define TICKS_DAY (TICKS_HOUR * ((uint64_t)24))
+#define TICKS_HOUR (TICKS_MINUTE * ((uint64_t)60))
+#define TICKS_MINUTE (TICKS_SECOND * ((uint64_t)60))
+#define TICKS_SECOND ((uint64_t)1000)
+
+#define SLICES_COUNT (sizeof(ticks_per_slice) / sizeof(ticks_per_slice[0]))
+
+uint64_t ticks_per_slice[] =
+{
+ TICKS_YEAR,
+ TICKS_MONTH,
+ TICKS_WEEK,
+ TICKS_DAY,
+ TICKS_HOUR,
+ TICKS_MINUTE,
+ TICKS_SECOND,
+ 1
+};
+
+_TCHAR * slice_names_singular[] =
+{
+ _T("year"),
+ _T("month"),
+ _T("week"),
+ _T("day"),
+ _T("hour"),
+ _T("minute"),
+ _T("second"),
+ _T("millisecond")
+};
+
+_TCHAR * slice_names_plural[] =
+{
+ _T("years"),
+ _T("months"),
+ _T("weeks"),
+ _T("days"),
+ _T("hours"),
+ _T("minutes"),
+ _T("seconds"),
+ _T("milliseconds")
+};
+
+void print_uptime
+(
+ uint64_t tickcount,
+ uint64_t prevsliceval,
+ _TCHAR * prevsliceunit,
+ int curslice
+)
+{
+ uint64_t tick_cur = tickcount / ticks_per_slice[curslice];
+ uint64_t tick_residual = tickcount % ticks_per_slice[curslice];
+
+ assert(tick_cur <= (~((unsigned)0)));
+
+ if(tick_residual == 0)
+ {
+ /* the current slice is the last */
+
+ if(prevsliceval == 0)
+ {
+ /* the current slice is the only */
+ _tprintf
+ (
+ _T("%u %s"),
+ (unsigned)tick_cur,
+ (tick_cur == 1 ? slice_names_singular : slice_names_plural)[curslice]
+ );
+ }
+ else
+ {
+ /* the current slice is the last, and there's a previous slice */
+ assert(prevsliceunit);
+
+ /* print the previous and the current slice, and terminate */
+ _tprintf
+ (
+ _T("%u %s %s %u %s"),
+ (unsigned)prevsliceval,
+ prevsliceunit,
+ _T("and"),
+ (unsigned)tick_cur,
+ (tick_cur == 1 ? slice_names_singular : slice_names_plural)[curslice]
+ );
+ }
+ }
+ else if(tick_cur != 0)
+ {
+ /* the current slice is not the last, and non-zero */
+
+ if(prevsliceval != 0)
+ {
+ /* there's a previous slice: print it */
+ assert(prevsliceunit);
+ _tprintf(_T("%u %s, "), (unsigned)prevsliceval, prevsliceunit);
+ }
+
+ /* recursion on the next slice size, storing the current slice */
+ print_uptime
+ (
+ tick_residual,
+ tick_cur,
+ (tick_cur == 1 ? slice_names_singular : slice_names_plural)[curslice],
+ curslice + 1
+ );
+ }
+ else
+ {
+ /*
+ the current slice is not the last, and zero: recursion, remembering the
+ previous non-zero slice
+ */
+ print_uptime(tick_residual, prevsliceval, prevsliceunit, curslice + 1);
+ }
+}
+
+int _tmain()
+{
+ print_uptime((uint64_t)GetTickCount(), 0, NULL, 0);
+ _puttc(_T('\n'), stdout);
+ return 0;
+}
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: drivers/fs/fs_rec/udfs.c
+ * PURPOSE: Filesystem recognizer driver
+ * PROGRAMMER: Eric Kohl
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+
+#define NDEBUG
+#include <debug.h>
+
+#include "fs_rec.h"
+
+
+#define UDFS_VRS_START_SECTOR 16
+#define UDFS_AVDP_SECTOR 256
+
+/* TYPES ********************************************************************/
+
+typedef struct _TAG
+{
+ USHORT Identifier;
+ USHORT Version;
+ UCHAR Checksum;
+ UCHAR Reserved;
+ USHORT SerialNumber;
+ USHORT Crc;
+ USHORT CrcLength;
+ ULONG Location;
+} PACKED TAG, *PTAG;
+
+typedef struct _EXTENT
+{
+ ULONG Length;
+ ULONG Location;
+} PACKED EXTENT, *PEXTENT;
+
+typedef struct _AVDP
+{
+ TAG DescriptorTag;
+ EXTENT MainVolumeDescriptorExtent;
+ EXTENT ReserveVolumeDescriptorExtent;
+} PACKED AVDP, *PAVDP;
+
+/* FUNCTIONS ****************************************************************/
+
+static NTSTATUS
+FsRecCheckVolumeRecognitionSequence(IN PDEVICE_OBJECT DeviceObject,
+ IN ULONG SectorSize)
+{
+ PUCHAR Buffer;
+ ULONG Sector;
+ NTSTATUS Status;
+ ULONG State;
+
+ Buffer = ExAllocatePool(NonPagedPool,
+ SectorSize);
+ if (Buffer == NULL)
+ {
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ State = 0;
+ Sector = UDFS_VRS_START_SECTOR;
+ while (TRUE)
+ {
+ Status = FsRecReadSectors(DeviceObject,
+ Sector,
+ 1,
+ SectorSize,
+ Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("FsRecReadSectors() failed (Status %lx)\n", Status);
+ break;
+ }
+
+ DPRINT1("Descriptor identifier: [%.5s]\n", Buffer + 1);
+
+ switch (State)
+ {
+ case 0:
+ if ((Sector == UDFS_VRS_START_SECTOR) &&
+ (Buffer[1] == 'B') &&
+ (Buffer[2] == 'E') &&
+ (Buffer[3] == 'A') &&
+ (Buffer[4] == '0') &&
+ (Buffer[5] == '1'))
+ {
+ State = 1;
+ }
+ else
+ {
+ DPRINT1("VRS start sector is not 'BEA01'\n");
+ ExFreePool(Buffer);
+ return(STATUS_UNRECOGNIZED_VOLUME);
+ }
+ break;
+
+ case 1:
+ if ((Buffer[1] == 'N') &&
+ (Buffer[2] == 'S') &&
+ (Buffer[3] == 'R') &&
+ (Buffer[4] == '0') &&
+ ((Buffer[5] == '2') || (Buffer[5] == '3')))
+ {
+ State = 2;
+ }
+ break;
+
+ case 2:
+ if ((Buffer[1] == 'T') &&
+ (Buffer[2] == 'E') &&
+ (Buffer[3] == 'A') &&
+ (Buffer[4] == '0') &&
+ (Buffer[5] == '1'))
+ {
+ DPRINT1("Found 'TEA01'\n");
+ ExFreePool(Buffer);
+ return(STATUS_SUCCESS);
+ }
+ break;
+ }
+
+ Sector++;
+ if (Sector == UDFS_AVDP_SECTOR)
+ {
+ DPRINT1("No 'TEA01' found\n");
+ ExFreePool(Buffer);
+ return(STATUS_UNRECOGNIZED_VOLUME);
+ }
+ }
+
+ ExFreePool(Buffer);
+
+ return(STATUS_UNRECOGNIZED_VOLUME);
+}
+
+
+static NTSTATUS
+FsRecCheckAnchorVolumeDescriptorPointer(IN PDEVICE_OBJECT DeviceObject,
+ IN ULONG SectorSize)
+{
+ PUCHAR Buffer;
+ ULONG Sector;
+ NTSTATUS Status;
+ PAVDP Avdp;
+
+ Buffer = ExAllocatePool(NonPagedPool,
+ SectorSize);
+ if (Buffer == NULL)
+ {
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ Sector = UDFS_AVDP_SECTOR;
+ Status = FsRecReadSectors(DeviceObject,
+ Sector,
+ 1,
+ SectorSize,
+ Buffer);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("FsRecReadSectors() failed (Status %lx)\n", Status);
+ ExFreePool(Buffer);
+ return(Status);
+ }
+
+ Avdp = (PAVDP)Buffer;
+ DPRINT1("Descriptor identifier: %hu\n", Avdp->DescriptorTag.Identifier);
+
+ DPRINT1("Main volume descriptor sequence location: %lu\n",
+ Avdp->MainVolumeDescriptorExtent.Location);
+
+ DPRINT1("Main volume descriptor sequence length: %lu\n",
+ Avdp->MainVolumeDescriptorExtent.Length);
+
+ DPRINT1("Reserve volume descriptor sequence location: %lu\n",
+ Avdp->ReserveVolumeDescriptorExtent.Location);
+
+ DPRINT1("Reserve volume descriptor sequence length: %lu\n",
+ Avdp->ReserveVolumeDescriptorExtent.Length);
+
+ ExFreePool(Buffer);
+
+// return(Status);
+ return(STATUS_SUCCESS);
+}
+
+
+static NTSTATUS
+FsRecIsUdfsVolume(IN PDEVICE_OBJECT DeviceObject)
+{
+ DISK_GEOMETRY DiskGeometry;
+ ULONG Size;
+ NTSTATUS Status;
+
+ Size = sizeof(DISK_GEOMETRY);
+ Status = FsRecDeviceIoControl(DeviceObject,
+ IOCTL_CDROM_GET_DRIVE_GEOMETRY,
+ NULL,
+ 0,
+ &DiskGeometry,
+ &Size);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("FsRecDeviceIoControl() failed (Status %lx)\n", Status);
+ return(Status);
+ }
+ DPRINT1("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector);
+
+ /* Check the volume recognition sequence */
+ Status = FsRecCheckVolumeRecognitionSequence(DeviceObject,
+ DiskGeometry.BytesPerSector);
+ if (!NT_SUCCESS(Status))
+ return(Status);
+
+ Status = FsRecCheckAnchorVolumeDescriptorPointer(DeviceObject,
+ DiskGeometry.BytesPerSector);
+ if (!NT_SUCCESS(Status))
+ return(Status);
+
+
+ return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS
+FsRecUdfsFsControl(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION Stack;
+ UNICODE_STRING RegistryPath;
+ NTSTATUS Status;
+
+ Stack = IoGetCurrentIrpStackLocation(Irp);
+
+ switch (Stack->MinorFunction)
+ {
+ case IRP_MN_MOUNT_VOLUME:
+ DPRINT("Udfs: IRP_MN_MOUNT_VOLUME\n");
+ Status = FsRecIsUdfsVolume(Stack->Parameters.MountVolume.DeviceObject);
+ if (NT_SUCCESS(Status))
+ {
+ DPRINT("Identified UDFS volume\n");
+ Status = STATUS_FS_DRIVER_REQUIRED;
+ }
+ break;
+
+ case IRP_MN_LOAD_FILE_SYSTEM:
+ DPRINT("Udfs: IRP_MN_LOAD_FILE_SYSTEM\n");
+ RtlInitUnicodeStringFromLiteral(&RegistryPath,
+ L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Udfs");
+ Status = ZwLoadDriver(&RegistryPath);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ZwLoadDriver failed (Status %x)\n", Status);
+ }
+ else
+ {
+ IoUnregisterFileSystem(DeviceObject);
+ }
+ break;
+
+ default:
+ DPRINT("Udfs: Unknown minor function %lx\n", Stack->MinorFunction);
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ break;
+ }
+ return(Status);
+}
+
+/* EOF */
--- /dev/null
+/* $Id$
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: drivers/fs/vfat/flush.c
+ * PURPOSE: VFAT Filesystem
+ * PROGRAMMER: Hartmut Birr
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include "vfat.h"
+
+#define NDEBUG
+#include <debug.h>
+
+/* FUNCTIONS ****************************************************************/
+
+NTSTATUS VfatFlushFile(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
+{
+ IO_STATUS_BLOCK IoStatus;
+
+ DPRINT("VfatFlushFile(DeviceExt %x, Fcb %x) for '%S'\n", DeviceExt, Fcb, Fcb->PathName);
+
+ CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, &IoStatus);
+ if (IoStatus.Status == STATUS_INVALID_PARAMETER)
+ {
+ /* FIXME: Caching was possible not initialized */
+ IoStatus.Status = STATUS_SUCCESS;
+ }
+ return IoStatus.Status;
+}
+
+NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb)
+{
+ PLIST_ENTRY ListEntry;
+ PVFATFCB Fcb;
+ PVFATCCB Ccb;
+ NTSTATUS Status, ReturnStatus = STATUS_SUCCESS;
+
+ DPRINT("VfatFlushVolume(DeviceExt %x, FatFcb %x)\n", DeviceExt, VolumeFcb);
+
+ ListEntry = DeviceExt->FcbListHead.Flink;
+ while (ListEntry != &DeviceExt->FcbListHead)
+ {
+ Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
+ ListEntry = ListEntry->Flink;
+ ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
+ Status = VfatFlushFile(DeviceExt, Fcb);
+ ExReleaseResourceLite (&Fcb->MainResource);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("VfatFlushFile failed, status = %x\n", Status);
+ ReturnStatus = Status;
+ }
+ /* FIXME: Stop flushing if this a removable media and the media was removed */
+ }
+
+ Ccb = (PVFATCCB) DeviceExt->FATFileObject->FsContext2;
+ Fcb = Ccb->pFcb;
+
+ ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
+ Status = VfatFlushFile(DeviceExt, Fcb);
+ ExReleaseResourceLite(&DeviceExt->FatResource);
+
+ /* FIXME: Flush the buffers from storage device */
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("VfatFlushFile failed, status = %x\n", Status);
+ ReturnStatus = Status;
+ }
+
+ return ReturnStatus;
+}
+
+NTSTATUS VfatFlush(PVFAT_IRP_CONTEXT IrpContext)
+{
+ NTSTATUS Status;
+ PVFATFCB Fcb;
+ PVFATCCB Ccb;
+ /*
+ * This request is not allowed on the main device object.
+ */
+ if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
+ {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ goto ByeBye;
+ }
+
+ Ccb = (PVFATCCB) IrpContext->FileObject->FsContext2;
+ assert(Ccb);
+ Fcb = Ccb->pFcb;
+ assert(Fcb);
+
+ if (Fcb->Flags & FCB_IS_VOLUME)
+ {
+ ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, TRUE);
+ Status = VfatFlushVolume(IrpContext->DeviceExt, Fcb);
+ ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
+ }
+ else
+ {
+ ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
+ Status = VfatFlushFile(IrpContext->DeviceExt, Fcb);
+ ExReleaseResourceLite (&Fcb->MainResource);
+ }
+
+ByeBye:
+ IrpContext->Irp->IoStatus.Status = Status;
+ IrpContext->Irp->IoStatus.Information = 0;
+ IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT);
+ VfatFreeIrpContext(IrpContext);
+
+ return (Status);
+}
+
+/* EOF */
--- /dev/null
+unbzip2.sys
+unbzip2.nostrip.sys
+unbzip2.sym
+*.d
+*.o
\ No newline at end of file
--- /dev/null
+*.o
+*.sym
+*.d
--- /dev/null
+*.coff
+*.d
+*.o
+*.sym
+*.sys
--- /dev/null
+# $Id$
+
+PATH_TO_TOP = ../../..
+
+#TARGET_TYPE = export_driver
+TARGET_TYPE = driver
+
+TARGET_NAME = npf
+
+#TARGET_CFLAGS = -DDBG -DWIN_NT_DRIVER -DKQPC_TS -I$(PATH_TO_TOP)/ntoskrnl/include
+
+TARGET_CFLAGS = -DDBG -DWIN_NT_DRIVER -DKQPC_TS -DUSE_KLOCKS -I$(PATH_TO_TOP)/ntoskrnl/include
+
+TARGET_DDKLIBS = ndis.a
+
+TARGET_OBJECTS = \
+ packet.o \
+ openclos.o \
+ read.o \
+ write.o \
+ dump.o \
+ jitter.o \
+ win_bpf_filter.o \
+ tme.o \
+ count_packets.o \
+ win_bpf_filter_init.o \
+ tcp_session.o \
+ memory_t.o \
+ time_calls.o \
+ functions.o \
+ bucket_lookup.o \
+ normal_lookup.o
+
+TARGET_PATH = .
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
--- /dev/null
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "bucket_lookup.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/tme/bucket_lookup.h>
+#else
+#include <tme/tme.h>
+#include <tme/bucket_lookup.h>
+#endif
+
+#endif
+
+
+
+/* the key is represented by the initial and final value */
+/* of the bucket. At the moment bucket_lookup is able to */
+/* manage values of 16, 32 bits. */
+uint32 bucket_lookup(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
+{
+ uint32 value;
+ uint32 i,j;
+ int found=-1;
+ uint32 blocks;
+ uint32 block_size;
+ uint8 *temp;
+ if ((data->key_len!=1)&& /*16 bit value*/
+ (data->key_len!=2)) /*32 bit value*/
+ return TME_ERROR;
+
+ /*32 bit values*/
+ blocks=data->filled_blocks-1;
+ block_size=data->block_size;
+ i=blocks/2; /*relative shift*/
+ j=i;
+ temp=data->shared_memory_base_address+block_size;
+
+ if (data->key_len==2)
+ {
+ value=SW_ULONG_AT(key,0);
+
+ if((value<SW_ULONG_AT(temp,0))||(value>SW_ULONG_AT(temp+block_size*(blocks-1),4)))
+ {
+ uint32 *key32=(uint32*) key;
+ key32[0]=key32[1]=0;
+
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+8),time_ref);
+
+ data->last_found=NULL;
+ return TME_FALSE;
+ }
+
+ while(found==-1) /* search routine */
+ {
+ i=(i==1)? 1:i>>1;
+ if (SW_ULONG_AT(temp+block_size*j,0)>value)
+ if (SW_ULONG_AT(temp+block_size*(j-1),4)<value)
+ found=-2;
+ else
+ j-=i;
+ else
+ if (SW_ULONG_AT(temp+block_size*j,4)<value)
+ if (SW_ULONG_AT(temp+block_size*j,0)>value)
+ found=-2;
+ else
+ j+=i;
+ else found=j;
+ }
+ if (found<0)
+ {
+ uint32 *key32=(uint32*) key;
+ key32[0]=key32[1]=0;
+
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+8),time_ref);
+
+ data->last_found=NULL;
+ return TME_FALSE;
+ }
+
+ data->last_found=data->lut_base_address+found*sizeof(RECORD);
+
+ COPY_MEMORY(key,temp+block_size*found,8);
+
+ GET_TIME((struct timeval *)(temp+block_size*found+8),time_ref);
+
+ return TME_TRUE;
+ }
+ else
+ {
+ value=SW_USHORT_AT(key,0);
+
+ if((value<SW_USHORT_AT(temp,0))||(value>SW_USHORT_AT(temp+block_size*(blocks-1),2)))
+ {
+ uint16 *key16=(uint16*) key;
+ key16[0]=key16[1]=0;
+
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+4),time_ref);
+
+ data->last_found=NULL;
+ return TME_FALSE;
+ }
+
+ while(found==-1) /* search routine */
+ {
+ i=(i==1)? 1:i>>1;
+ if (SW_USHORT_AT(temp+block_size*j,0)>value)
+ if (SW_USHORT_AT(temp+block_size*(j-1),2)<value)
+ found=-2;
+ else
+ j-=i;
+ else
+ if (SW_USHORT_AT(temp+block_size*j,2)<value)
+ if (SW_USHORT_AT(temp+block_size*j,0)>value)
+ found=-2;
+ else
+ j+=i;
+ else found=j;
+ }
+
+ if (found<0)
+ {
+ uint16 *key16=(uint16*) key;
+ key16[0]=key16[1]=0;
+
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+4),time_ref);
+
+ data->last_found=NULL;
+ return TME_FALSE;
+ }
+
+ data->last_found=data->lut_base_address+found*sizeof(RECORD);
+
+ GET_TIME((struct timeval *)(temp+block_size*found+4),time_ref);
+
+ COPY_MEMORY(key,temp+block_size*found,4);
+
+ return TME_TRUE;
+ }
+
+}
+
+uint32 bucket_lookup_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
+{
+ RECORD *records=(RECORD*)data->lut_base_address;
+
+ if ((data->key_len!=1)&& /*16 bit value*/
+ (data->key_len!=2)) /*32 bit value*/
+ return TME_ERROR;
+
+ if(data->key_len==2)
+ {
+ uint32 start,stop;
+ uint8 *tmp;
+
+ start=SW_ULONG_AT(key,0);
+ stop=SW_ULONG_AT(key,4);
+
+ if (start>stop)
+ return TME_ERROR;
+ if (data->filled_entries>0)
+ {
+ tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries-1].block,0);
+ /*check if it is coherent with the previous block*/
+ if (SW_ULONG_AT(tmp,4)>=start)
+ return TME_ERROR;
+ }
+
+ if (data->filled_blocks==data->shared_memory_blocks)
+ return TME_ERROR;
+
+ if (data->filled_entries==data->lut_entries)
+ return TME_ERROR;
+
+ tmp=data->shared_memory_base_address+data->block_size*data->filled_blocks;
+
+ COPY_MEMORY(tmp,key,8);
+
+ SW_ULONG_ASSIGN(&records[data->filled_entries].block,tmp-mem_ex->buffer);
+ SW_ULONG_ASSIGN(&records[data->filled_entries].exec_fcn,data->default_exec);
+
+ GET_TIME((struct timeval *)(tmp+8),time_ref);
+
+ data->filled_blocks++;
+ data->filled_entries++;
+
+ return TME_TRUE;
+ }
+ else
+ {
+ uint16 start,stop;
+ uint8 *tmp;
+
+ start=SW_USHORT_AT(key,0);
+ stop=SW_USHORT_AT(key,2);
+
+ if (start>stop)
+ return TME_ERROR;
+ if (data->filled_entries>0)
+ {
+ tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries-1].block,0);
+ /*check if it is coherent with the previous block*/
+ if (SW_USHORT_AT(tmp,2)>=start)
+ return TME_ERROR;
+ }
+
+ if (data->filled_blocks==data->shared_memory_blocks)
+ return TME_ERROR;
+
+ if (data->filled_entries==data->lut_entries)
+ return TME_ERROR;
+
+ tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries].block,0);
+
+ COPY_MEMORY(tmp,key,4);
+
+ SW_ULONG_ASSIGN(&records[data->filled_entries].block,tmp-mem_ex->buffer);
+ SW_ULONG_ASSIGN(&records[data->filled_entries].exec_fcn,data->default_exec);
+
+ GET_TIME((struct timeval *)(tmp+4),time_ref);
+
+ data->filled_blocks++;
+ data->filled_entries++;
+
+ return TME_TRUE;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __bucket_lookup
+#define __bucket_lookup
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+
+#define BUCKET_LOOKUP_INSERT 0x00000011
+uint32 bucket_lookup_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
+#define BUCKET_LOOKUP 0x00000010
+uint32 bucket_lookup(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
+
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "count_packets.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/tme/count_packets.h>
+#else
+#include <tme/tme.h>
+#include <tme/count_packets.h>
+#endif
+
+#endif
+
+
+
+uint32 count_packets(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data)
+{
+
+ c_p_data *counters=(c_p_data*)(block+data->key_len*4);
+
+ counters->bytes+=pkt_size;
+ counters->packets++;
+
+ return TME_SUCCESS;
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __count_packets
+#define __count_packets
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+
+typedef struct __c_p_data
+{
+ struct timeval timestamp;
+ uint64 packets;
+ uint64 bytes;
+}
+ c_p_data;
+
+#define COUNT_PACKETS 0x00000000
+uint32 count_packets(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
+
+#endif
+
--- /dev/null
+/*
+ * Copyright (c) 1999, 2000
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __DEBUG_INCLUDE
+#define __DEBUG_INCLUDE
+
+
+#if DBG
+
+#define IF_PACKETDEBUG(f) if (PacketDebugFlag & (f))
+extern ULONG PacketDebugFlag;
+
+#define PACKET_DEBUG_LOUD 0x00000001 // debugging info
+#define PACKET_DEBUG_VERY_LOUD 0x00000002 // excessive debugging info
+
+#define PACKET_DEBUG_INIT 0x00000100 // init debugging info
+
+//
+// Macro for deciding whether to dump lots of debugging information.
+//
+
+#define IF_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_LOUD ) { A }
+#define IF_VERY_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_VERY_LOUD ) { A }
+#define IF_INIT_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_INIT ) { A }
+
+#else
+
+#define IF_LOUD(A)
+#define IF_VERY_LOUD(A)
+#define IF_INIT_LOUD(A)
+
+#endif
+
+#endif /*#define __DEBUG_INCLUDE*/
--- /dev/null
+/*
+ * Copyright (c) 1999, 2000
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef _MSC_VER
+#include "stdarg.h"
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+#else
+#include <ddk/ntddk.h>
+#include <net/ndis.h>
+//#define PsGetCurrentProcess() IoGetCurrentProcess()
+#define PsGetCurrentThread() ((PETHREAD) (KeGetCurrentThread()))
+#endif
+
+#include "debug.h"
+#include "packet.h"
+#include "win_bpf.h"
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_OpenDumpFile(POPEN_INSTANCE Open , PUNICODE_STRING fileName, BOOLEAN Append)
+{
+ NTSTATUS ntStatus;
+ IO_STATUS_BLOCK IoStatus;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PWCHAR PathPrefix;
+ USHORT PathLen;
+ UNICODE_STRING FullFileName;
+ ULONG FullFileNameLength;
+ PDEVICE_OBJECT fsdDevice;
+
+ FILE_STANDARD_INFORMATION StandardInfo;
+
+ IF_LOUD(DbgPrint("NPF: OpenDumpFile.\n");)
+
+ if(fileName->Buffer[0] == L'\\' &&
+ fileName->Buffer[1] == L'?' &&
+ fileName->Buffer[2] == L'?' &&
+ fileName->Buffer[3] == L'\\'
+ ){
+ PathLen = 0;
+ }
+ else{
+ PathPrefix = L"\\??\\";
+ PathLen = 8;
+ }
+
+ // Insert the correct path prefix.
+ FullFileNameLength = PathLen + fileName->MaximumLength;
+
+#define NPF_TAG_FILENAME TAG('0', 'D', 'W', 'A')
+ FullFileName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
+ FullFileNameLength,
+ NPF_TAG_FILENAME);
+
+ if (FullFileName.Buffer == NULL) {
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ return ntStatus;
+ }
+
+ FullFileName.Length = PathLen;
+ FullFileName.MaximumLength = (USHORT)FullFileNameLength;
+
+ if(PathLen)
+ RtlMoveMemory (FullFileName.Buffer, PathPrefix, PathLen);
+
+ RtlAppendUnicodeStringToString (&FullFileName, fileName);
+
+ IF_LOUD(DbgPrint( "Packet: Attempting to open %wZ\n", &FullFileName);)
+
+ InitializeObjectAttributes ( &ObjectAttributes,
+ &FullFileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+
+ // Create the dump file
+ ntStatus = ZwCreateFile( &Open->DumpFileHandle,
+ SYNCHRONIZE | FILE_WRITE_DATA,
+ &ObjectAttributes,
+ &IoStatus,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ,
+ (Append)?FILE_OPEN_IF:FILE_SUPERSEDE,
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0 );
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error opening file %x\n", ntStatus);)
+
+ ExFreePool(FullFileName.Buffer);
+ Open->DumpFileHandle=NULL;
+ ntStatus = STATUS_NO_SUCH_FILE;
+ return ntStatus;
+ }
+
+ ExFreePool(FullFileName.Buffer);
+
+ ntStatus = ObReferenceObjectByHandle(Open->DumpFileHandle,
+ FILE_WRITE_ACCESS,
+#ifndef __GNUC__
+ *IoFileObjectType,
+#else
+ IoFileObjectType,
+#endif
+ KernelMode,
+ (PVOID)&Open->DumpFileObject,
+ 0);
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error creating file, status=%x\n", ntStatus);)
+
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ ntStatus = STATUS_NO_SUCH_FILE;
+ return ntStatus;
+ }
+
+ fsdDevice = IoGetRelatedDeviceObject(Open->DumpFileObject);
+
+ IF_LOUD(DbgPrint("NPF: Dump: write file created succesfully, status=%d \n",ntStatus);)
+
+ return ntStatus;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_StartDump(POPEN_INSTANCE Open)
+{
+ NTSTATUS ntStatus;
+ struct packet_file_header hdr;
+ IO_STATUS_BLOCK IoStatus;
+ NDIS_REQUEST pRequest;
+ ULONG MediaType;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+
+ IF_LOUD(DbgPrint("NPF: StartDump.\n");)
+
+ // Init the file header
+ hdr.magic = TCPDUMP_MAGIC;
+ hdr.version_major = PCAP_VERSION_MAJOR;
+ hdr.version_minor = PCAP_VERSION_MINOR;
+ hdr.thiszone = 0; /*Currently not set*/
+ hdr.snaplen = 1514;
+ hdr.sigfigs = 0;
+
+ // Detect the medium type
+ switch (Open->Medium){
+
+ case NdisMediumWan:
+ hdr.linktype = DLT_EN10MB;
+ break;
+
+ case NdisMedium802_3:
+ hdr.linktype = DLT_EN10MB;
+ break;
+
+ case NdisMediumFddi:
+ hdr.linktype = DLT_FDDI;
+ break;
+
+ case NdisMedium802_5:
+ hdr.linktype = DLT_IEEE802;
+ break;
+
+ case NdisMediumArcnet878_2:
+ hdr.linktype = DLT_ARCNET;
+ break;
+
+ case NdisMediumAtm:
+ hdr.linktype = DLT_ATM_RFC1483;
+ break;
+
+ default:
+ hdr.linktype = DLT_EN10MB;
+ }
+
+ // Write the header.
+ // We can use ZwWriteFile because we are in the context of the application
+ ntStatus = ZwWriteFile(Open->DumpFileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatus,
+ &hdr,
+ sizeof(hdr),
+ NULL,
+ NULL );
+
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error dumping file %x\n", ntStatus);)
+
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ ntStatus = STATUS_NO_SUCH_FILE;
+ return ntStatus;
+ }
+
+ Open->DumpOffset.QuadPart=24;
+
+ ntStatus = PsCreateSystemThread(&Open->DumpThreadHandle,
+ THREAD_ALL_ACCESS,
+ (ACCESS_MASK)0L,
+ 0,
+ 0,
+ (PKSTART_ROUTINE)NPF_DumpThread,
+ Open);
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);)
+
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ return ntStatus;
+ }
+ ntStatus = ObReferenceObjectByHandle(Open->DumpThreadHandle,
+ THREAD_ALL_ACCESS,
+ NULL,
+ KernelMode,
+ (PVOID*)&Open->DumpThreadObject,
+ 0);
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);)
+
+ ObDereferenceObject(Open->DumpFileObject);
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ return ntStatus;
+ }
+
+ return ntStatus;
+
+}
+
+//-------------------------------------------------------------------
+// Dump Thread
+//-------------------------------------------------------------------
+
+VOID NPF_DumpThread(POPEN_INSTANCE Open)
+{
+ ULONG FrozenNic;
+
+ IF_LOUD(DbgPrint("NPF: In the work routine. Parameter = 0x%0x\n",Open);)
+
+ while(TRUE){
+
+ // Wait until some packets arrive or the timeout expires
+ NdisWaitEvent(&Open->DumpEvent, 5000);
+
+ IF_LOUD(DbgPrint("NPF: Worker Thread - event signalled\n");)
+
+ if(Open->DumpLimitReached ||
+ Open->BufSize==0){ // BufSize=0 means that this instance was closed, or that the buffer is too
+ // small for any capture. In both cases it is better to end the dump
+
+ IF_LOUD(DbgPrint("NPF: Worker Thread - Exiting happily\n");)
+ IF_LOUD(DbgPrint("Thread: Dumpoffset=%I64d\n",Open->DumpOffset.QuadPart);)
+
+ PsTerminateSystemThread(STATUS_SUCCESS);
+ return;
+ }
+
+ NdisResetEvent(&Open->DumpEvent);
+
+ // Write the content of the buffer to the file
+ if(NPF_SaveCurrentBuffer(Open) != STATUS_SUCCESS){
+ PsTerminateSystemThread(STATUS_SUCCESS);
+ return;
+ }
+
+ }
+
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open)
+{
+ UINT Thead;
+ UINT Ttail;
+ UINT TLastByte;
+ PUCHAR CurrBuff;
+ NTSTATUS ntStatus;
+ IO_STATUS_BLOCK IoStatus;
+ PMDL lMdl;
+ UINT SizeToDump;
+
+
+ Thead=Open->Bhead;
+ Ttail=Open->Btail;
+ TLastByte=Open->BLastByte;
+
+ IF_LOUD(DbgPrint("NPF: NPF_SaveCurrentBuffer.\n");)
+
+ // Get the address of the buffer
+ CurrBuff=Open->Buffer;
+ //
+ // Fill the application buffer
+ //
+ if( Ttail < Thead )
+ {
+ if(Open->MaxDumpBytes &&
+ (UINT)Open->DumpOffset.QuadPart + GetBuffOccupation(Open) > Open->MaxDumpBytes)
+ {
+ // Size limit reached
+ UINT PktLen;
+
+ SizeToDump = 0;
+
+ // Scan the buffer to detect the exact amount of data to save
+ while(TRUE){
+ PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
+
+ if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
+ break;
+
+ SizeToDump += PktLen;
+ }
+
+ }
+ else
+ SizeToDump = TLastByte-Thead;
+
+ lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
+ if (lMdl == NULL)
+ {
+ // No memory: stop dump
+ IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ MmBuildMdlForNonPagedPool(lMdl);
+
+ // Write to disk
+ NPF_WriteDumpFile(Open->DumpFileObject,
+ &Open->DumpOffset,
+ SizeToDump,
+ lMdl,
+ &IoStatus);
+
+ IoFreeMdl(lMdl);
+
+ if(!NT_SUCCESS(IoStatus.Status)){
+ // Error
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if(SizeToDump != TLastByte-Thead){
+ // Size limit reached.
+ Open->DumpLimitReached = TRUE;
+
+ // Awake the application
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Update the packet buffer
+ Open->DumpOffset.QuadPart+=(TLastByte-Thead);
+ Open->BLastByte=Ttail;
+ Open->Bhead=0;
+ }
+
+ if( Ttail > Thead ){
+
+ if(Open->MaxDumpBytes &&
+ (UINT)Open->DumpOffset.QuadPart + GetBuffOccupation(Open) > Open->MaxDumpBytes)
+ {
+ // Size limit reached
+ UINT PktLen;
+
+ SizeToDump = 0;
+
+ // Scan the buffer to detect the exact amount of data to save
+ while(Thead + SizeToDump < Ttail){
+
+ PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
+
+ if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
+ break;
+
+ SizeToDump += PktLen;
+ }
+
+ }
+ else
+ SizeToDump = Ttail-Thead;
+
+ lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
+ if (lMdl == NULL)
+ {
+ // No memory: stop dump
+ IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ MmBuildMdlForNonPagedPool(lMdl);
+
+ // Write to disk
+ NPF_WriteDumpFile(Open->DumpFileObject,
+ &Open->DumpOffset,
+ SizeToDump,
+ lMdl,
+ &IoStatus);
+
+ IoFreeMdl(lMdl);
+
+ if(!NT_SUCCESS(IoStatus.Status)){
+ // Error
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if(SizeToDump != Ttail-Thead){
+ // Size limit reached.
+ Open->DumpLimitReached = TRUE;
+
+ // Awake the application
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Update the packet buffer
+ Open->DumpOffset.QuadPart+=(Ttail-Thead);
+ Open->Bhead=Ttail;
+
+ }
+
+ return STATUS_SUCCESS;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open){
+ NTSTATUS ntStatus;
+ IO_STATUS_BLOCK IoStatus;
+ PMDL WriteMdl;
+ PUCHAR VMBuff;
+ UINT VMBufLen;
+
+
+ IF_LOUD(DbgPrint("NPF: NPF_CloseDumpFile.\n");)
+ IF_LOUD(DbgPrint("Dumpoffset=%d\n",Open->DumpOffset.QuadPart);)
+
+DbgPrint("1\n");
+ // Consistency check
+ if(Open->DumpFileHandle == NULL)
+ return STATUS_UNSUCCESSFUL;
+
+DbgPrint("2\n");
+ ZwClose( Open->DumpFileHandle );
+
+ ObDereferenceObject(Open->DumpFileObject);
+/*
+ if(Open->DumpLimitReached == TRUE)
+ // Limit already reached: don't save the rest of the buffer.
+ return STATUS_SUCCESS;
+*/
+DbgPrint("3\n");
+
+ NPF_OpenDumpFile(Open,&Open->DumpFileName, TRUE);
+
+ // Flush the buffer to file
+ NPF_SaveCurrentBuffer(Open);
+
+ // Close The file
+ ObDereferenceObject(Open->DumpFileObject);
+ ZwClose( Open->DumpFileHandle );
+
+ Open->DumpFileHandle = NULL;
+
+ ObDereferenceObject(Open->DumpFileObject);
+
+ return STATUS_SUCCESS;
+}
+
+//-------------------------------------------------------------------
+
+#ifndef __GNUC__
+static NTSTATUS
+#else
+NTSTATUS STDCALL
+#endif
+PacketDumpCompletion(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PVOID Context)
+{
+
+ // Copy the status information back into the "user" IOSB
+ *Irp->UserIosb = Irp->IoStatus;
+
+ // Wake up the mainline code
+ KeSetEvent(Irp->UserEvent, 0, FALSE);
+
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_WriteDumpFile(PFILE_OBJECT FileObject,
+ PLARGE_INTEGER Offset,
+ ULONG Length,
+ PMDL Mdl,
+ PIO_STATUS_BLOCK IoStatusBlock)
+{
+ PIRP irp;
+ KEVENT event;
+ PIO_STACK_LOCATION ioStackLocation;
+ PDEVICE_OBJECT fsdDevice = IoGetRelatedDeviceObject(FileObject);
+ NTSTATUS Status;
+
+ // Set up the event we'll use
+ KeInitializeEvent(&event, SynchronizationEvent, FALSE);
+
+ // Allocate and build the IRP we'll be sending to the FSD
+ irp = IoAllocateIrp(fsdDevice->StackSize, FALSE);
+
+ if (!irp) {
+ // Allocation failed, presumably due to memory allocation failure
+ IoStatusBlock->Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoStatusBlock->Information = 0;
+
+ return;
+ }
+
+ irp->MdlAddress = Mdl;
+ irp->UserEvent = &event;
+ irp->UserIosb = IoStatusBlock;
+ irp->Tail.Overlay.Thread = PsGetCurrentThread();
+ irp->Tail.Overlay.OriginalFileObject= FileObject;
+ irp->RequestorMode = KernelMode;
+
+ // Indicate that this is a WRITE operation
+ irp->Flags = IRP_WRITE_OPERATION;
+
+ // Set up the next I/O stack location
+ ioStackLocation = IoGetNextIrpStackLocation(irp);
+ ioStackLocation->MajorFunction = IRP_MJ_WRITE;
+ ioStackLocation->MinorFunction = 0;
+ ioStackLocation->DeviceObject = fsdDevice;
+ ioStackLocation->FileObject = FileObject;
+ IoSetCompletionRoutine(irp, PacketDumpCompletion, 0, TRUE, TRUE, TRUE);
+ ioStackLocation->Parameters.Write.Length = Length;
+ ioStackLocation->Parameters.Write.ByteOffset = *Offset;
+
+
+ // Send it on. Ignore the return code
+ (void) IoCallDriver(fsdDevice, irp);
+
+ // Wait for the I/O to complete.
+ KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0);
+
+ // Free the IRP now that we are done with it
+ IoFreeIrp(irp);
+
+ return;
+}
--- /dev/null
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "functions.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/bpf.h>
+#include <net/tme/functions.h>
+#else
+#include <tme/tme.h>
+#include <bpf.h>
+#include <tme/functions.h>
+#endif
+
+#endif
+
+
+
+lut_fcn lut_fcn_mapper(uint32 index)
+{
+
+ switch (index)
+ {
+ case NORMAL_LUT_W_INSERT:
+ return (lut_fcn) normal_lut_w_insert;
+
+ case NORMAL_LUT_WO_INSERT:
+ return (lut_fcn) normal_lut_wo_insert;
+
+ case BUCKET_LOOKUP:
+ return (lut_fcn) bucket_lookup;
+
+ case BUCKET_LOOKUP_INSERT:
+ return (lut_fcn) bucket_lookup_insert;
+
+ default:
+ return NULL;
+ }
+
+ return NULL;
+
+}
+
+exec_fcn exec_fcn_mapper(uint32 index)
+{
+ switch (index)
+ {
+ case COUNT_PACKETS:
+ return (exec_fcn) count_packets;
+
+ case TCP_SESSION:
+ return (exec_fcn) tcp_session;
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
--- /dev/null
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __FUNCTIONS
+#define __FUNCTIONS
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+/*function mappers */
+
+lut_fcn lut_fcn_mapper(uint32 index);
+exec_fcn exec_fcn_mapper(uint32 index);
+
+/* lookup functions */
+
+#ifdef WIN32
+#include "bucket_lookup.h"
+#include "normal_lookup.h"
+#endif
+
+#ifdef __FreeBSD__
+#include <net/tme/bucket_lookup.h>
+#include <net/tme/normal_lookup.h>
+#endif
+
+/* execution functions */
+
+#ifdef WIN32
+#include "count_packets.h"
+#include "tcp_session.h"
+#endif
+
+#ifdef __FreeBSD__
+#include <net/tme/count_packets.h>
+#include <ne/tme/tcp_session.h>
+#endif
+
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2002
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef _MSC_VER
+#include "stdarg.h"
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+#else
+#include <ddk/ntddk.h>
+#include <net/ndis.h>
+#endif
+
+#include "packet.h"
+#include "win_bpf.h"
+
+emit_func emitm;
+
+//
+// emit routine to update the jump table
+//
+void emit_lenght(binary_stream *stream, ULONG value, UINT len)
+{
+ (stream->refs)[stream->bpf_pc]+=len;
+ stream->cur_ip+=len;
+}
+
+//
+// emit routine to output the actual binary code
+//
+void emit_code(binary_stream *stream, ULONG value, UINT len)
+{
+
+ switch (len){
+
+ case 1:
+ stream->ibuf[stream->cur_ip]=(UCHAR)value;
+ stream->cur_ip++;
+ break;
+
+ case 2:
+ *((USHORT*)(stream->ibuf+stream->cur_ip))=(USHORT)value;
+ stream->cur_ip+=2;
+ break;
+
+ case 4:
+ *((ULONG*)(stream->ibuf+stream->cur_ip))=value;
+ stream->cur_ip+=4;
+ break;
+
+ default:;
+
+ }
+
+ return;
+
+}
+
+//
+// Function that does the real stuff
+//
+BPF_filter_function BPFtoX86(struct bpf_insn *prog, UINT nins, INT *mem)
+{
+ struct bpf_insn *ins;
+ UINT i, pass;
+ binary_stream stream;
+
+
+ // Allocate the reference table for the jumps
+#ifdef NTKERNEL
+#define NPF_TAG_REFTABLE TAG('0', 'J', 'W', 'A')
+ stream.refs=(UINT *)ExAllocatePoolWithTag(NonPagedPool, (nins + 1)*sizeof(UINT), NPF_TAG_REFTABLE);
+#else
+ stream.refs=(UINT *)malloc((nins + 1)*sizeof(UINT));
+#endif
+ if(stream.refs==NULL)
+ {
+ return NULL;
+ }
+
+ // Reset the reference table
+ for(i=0; i< nins + 1; i++)
+ stream.refs[i]=0;
+
+ stream.cur_ip=0;
+ stream.bpf_pc=0;
+
+ // the first pass will emit the lengths of the instructions
+ // to create the reference table
+ emitm=emit_lenght;
+
+ for(pass=0;;){
+
+ ins = prog;
+
+ /* create the procedure header */
+ PUSH(EBP)
+ MOVrd(EBP,ESP)
+ PUSH(EBX)
+ PUSH(ECX)
+ PUSH(EDX)
+ PUSH(ESI)
+ PUSH(EDI)
+ MOVodd(EBX, EBP, 8)
+
+ for(i=0;i<nins;i++){
+
+ stream.bpf_pc++;
+
+ switch (ins->code) {
+
+ default:
+
+ return NULL;
+
+ case BPF_RET|BPF_K:
+
+ MOVid(EAX,ins->k)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ RET()
+
+ break;
+
+
+ case BPF_RET|BPF_A:
+
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ RET()
+
+ break;
+
+
+ case BPF_LD|BPF_W|BPF_ABS:
+
+ MOVid(ECX,ins->k)
+ MOVrd(ESI,ECX)
+ ADDib(ECX,sizeof(INT))
+ CMPodd(ECX, EBP, 0x10)
+ JLEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0) //this can be optimized with xor eax,eax
+ RET()
+ MOVobd(EAX, EBX, ESI)
+ BSWAP(EAX)
+
+ break;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+
+ MOVid(ECX,ins->k)
+ MOVrd(ESI,ECX)
+ ADDib(ECX,sizeof(SHORT))
+ CMPodd(ECX, EBP, 0x10)
+ JLEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVid(EAX,0)
+ MOVobw(AX, EBX, ESI)
+ SWAP_AX()
+
+ break;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+
+ MOVid(ECX,ins->k)
+ CMPodd(ECX, EBP, 0x10)
+ JLEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVid(EAX,0)
+ MOVobb(AL,EBX,ECX)
+
+ break;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+
+ MOVodd(EAX, EBP, 0xc)
+
+ break;
+
+ case BPF_LDX|BPF_W|BPF_LEN:
+
+ MOVodd(EDX, EBP, 0xc)
+
+ break;
+
+ case BPF_LD|BPF_W|BPF_IND:
+
+ MOVid(ECX,ins->k)
+ ADDrd(ECX,EDX)
+ MOVrd(ESI,ECX)
+ ADDib(ECX,sizeof(INT))
+ CMPodd(ECX, EBP, 0x10)
+ JLEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVobd(EAX, EBX, ESI)
+ BSWAP(EAX)
+
+ break;
+
+ case BPF_LD|BPF_H|BPF_IND:
+
+ MOVid(ECX,ins->k)
+ ADDrd(ECX,EDX)
+ MOVrd(ESI,ECX)
+ ADDib(ECX,sizeof(SHORT))
+ CMPodd(ECX, EBP, 0x10)
+ JLEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVid(EAX,0)
+ MOVobw(AX, EBX, ESI)
+ SWAP_AX()
+
+ break;
+
+ case BPF_LD|BPF_B|BPF_IND:
+
+ MOVid(ECX,ins->k)
+ ADDrd(ECX,EDX)
+ CMPodd(ECX, EBP, 0x10)
+ JLEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVid(EAX,0)
+ MOVobb(AL,EBX,ECX)
+
+ break;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+
+ MOVid(ECX,ins->k)
+ CMPodd(ECX, EBP, 0x10)
+ JLEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVid(EDX,0)
+ MOVobb(DL,EBX,ECX)
+ ANDib(DL, 0xf)
+ SHLib(EDX, 2)
+
+ break;
+
+ case BPF_LD|BPF_IMM:
+
+ MOVid(EAX,ins->k)
+
+ break;
+
+ case BPF_LDX|BPF_IMM:
+
+ MOVid(EDX,ins->k)
+
+ break;
+
+ case BPF_LD|BPF_MEM:
+
+ MOVid(ECX,(INT)mem)
+ MOVid(ESI,ins->k*4)
+ MOVobd(EAX, ECX, ESI)
+
+ break;
+
+ case BPF_LDX|BPF_MEM:
+
+ MOVid(ECX,(INT)mem)
+ MOVid(ESI,ins->k*4)
+ MOVobd(EDX, ECX, ESI)
+
+ break;
+
+ case BPF_ST:
+
+ // XXX: this command and the following could be optimized if the previous
+ // instruction was already of this type
+ MOVid(ECX,(INT)mem)
+ MOVid(ESI,ins->k*4)
+ MOVomd(ECX, ESI, EAX)
+
+ break;
+
+ case BPF_STX:
+
+ MOVid(ECX,(INT)mem)
+ MOVid(ESI,ins->k*4)
+ MOVomd(ECX, ESI, EDX)
+ break;
+
+ case BPF_JMP|BPF_JA:
+
+ JMP(stream.refs[stream.bpf_pc+ins->k]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+
+ CMPid(EAX, ins->k)
+ JG(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) // 5 is the size of the following JMP
+ JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
+ break;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+
+ CMPid(EAX, ins->k)
+ JGE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+
+ CMPid(EAX, ins->k)
+ JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+
+ MOVrd(ECX,EAX)
+ ANDid(ECX,ins->k)
+ JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+
+ CMPrd(EAX, EDX)
+ JA(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
+ break;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+
+ CMPrd(EAX, EDX)
+ JAE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+
+ CMPrd(EAX, EDX)
+ JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+
+ MOVrd(ECX,EAX)
+ ANDrd(ECX,EDX)
+ JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+
+ ADDrd(EAX,EDX)
+
+ break;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+
+ SUBrd(EAX,EDX)
+
+ break;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+
+ MOVrd(ECX,EDX)
+ MULrd(EDX)
+ MOVrd(EDX,ECX)
+ break;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+
+ CMPid(EDX, 0)
+ JNEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVrd(ECX,EDX)
+ MOVid(EDX,0)
+ DIVrd(ECX)
+ MOVrd(EDX,ECX)
+
+ break;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+
+ ANDrd(EAX,EDX)
+
+ break;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+
+ ORrd(EAX,EDX)
+
+ break;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+
+ MOVrd(ECX,EDX)
+ SHL_CLrb(EAX)
+
+ break;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+
+ MOVrd(ECX,EDX)
+ SHR_CLrb(EAX)
+
+ break;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+
+ ADD_EAXi(ins->k)
+
+ break;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+
+ SUB_EAXi(ins->k)
+
+ break;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+
+ MOVrd(ECX,EDX)
+ MOVid(EDX,ins->k)
+ MULrd(EDX)
+ MOVrd(EDX,ECX)
+
+ break;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+
+ MOVrd(ECX,EDX)
+ MOVid(EDX,0)
+ MOVid(ESI,ins->k)
+ DIVrd(ESI)
+ MOVrd(EDX,ECX)
+
+ break;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+
+ ANDid(EAX, ins->k)
+
+ break;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+
+ ORid(EAX, ins->k)
+
+ break;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+
+ SHLib(EAX, (ins->k) & 255)
+
+ break;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+
+ SHRib(EAX, (ins->k) & 255)
+
+ break;
+
+ case BPF_ALU|BPF_NEG:
+
+ NEGd(EAX)
+
+ break;
+
+ case BPF_MISC|BPF_TAX:
+
+ MOVrd(EDX,EAX)
+
+ break;
+
+ case BPF_MISC|BPF_TXA:
+
+ MOVrd(EAX,EDX)
+
+ break;
+
+
+
+ }
+
+ ins++;
+ }
+
+ pass++;
+ if(pass == 2) break;
+
+#ifdef NTKERNEL
+#define NPF_TAG_STREAMBUF TAG('1', 'J', 'W', 'A')
+ stream.ibuf=(CHAR*)ExAllocatePoolWithTag(NonPagedPool, stream.cur_ip, NPF_TAG_STREAMBUF);
+#else
+ stream.ibuf=(CHAR*)malloc(stream.cur_ip);
+#endif
+ if(stream.ibuf==NULL)
+ {
+#ifdef NTKERNEL
+ ExFreePool(stream.refs);
+#else
+ free(stream.refs);
+#endif
+ return NULL;
+ }
+
+ // modify the reference table to contain the offsets and not the lengths of the instructions
+ for(i=1; i< nins + 1; i++)
+ stream.refs[i]+=stream.refs[i-1];
+
+ // Reset the counters
+ stream.cur_ip=0;
+ stream.bpf_pc=0;
+ // the second pass creates the actual code
+ emitm=emit_code;
+
+ }
+
+ // the reference table is needed only during compilation, now we can free it
+#ifdef NTKERNEL
+ ExFreePool(stream.refs);
+#else
+ free(stream.refs);
+#endif
+ return (BPF_filter_function)stream.ibuf;
+
+}
+
+
+JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins)
+{
+ JIT_BPF_Filter *Filter;
+
+
+ // Allocate the filter structure
+#ifdef NTKERNEL
+#define NPF_TAG_FILTSTRUCT TAG('2', 'J', 'W', 'A')
+ Filter=(struct JIT_BPF_Filter*)ExAllocatePoolWithTag(NonPagedPool, sizeof(struct JIT_BPF_Filter), NPF_TAG_FILTSTRUCT);
+#else
+ Filter=(struct JIT_BPF_Filter*)malloc(sizeof(struct JIT_BPF_Filter));
+#endif
+ if(Filter==NULL)
+ {
+ return NULL;
+ }
+
+ // Allocate the filter's memory
+#ifdef NTKERNEL
+#define NPF_TAG_FILTMEM TAG('3', 'J', 'W', 'A')
+ Filter->mem=(INT*)ExAllocatePoolWithTag(NonPagedPool, BPF_MEMWORDS*sizeof(INT), NPF_TAG_FILTMEM);
+#else
+ Filter->mem=(INT*)malloc(BPF_MEMWORDS*sizeof(INT));
+#endif
+ if(Filter->mem==NULL)
+ {
+#ifdef NTKERNEL
+ ExFreePool(Filter);
+#else
+ free(Filter);
+#endif
+ return NULL;
+ }
+
+ // Create the binary
+ if((Filter->Function = BPFtoX86(fp, nins, Filter->mem))==NULL)
+ {
+#ifdef NTKERNEL
+ ExFreePool(Filter->mem);
+ ExFreePool(Filter);
+#else
+ free(Filter->mem);
+ free(Filter);
+
+ return NULL;
+#endif
+ }
+
+ return Filter;
+
+}
+
+//////////////////////////////////////////////////////////////
+
+void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter){
+
+#ifdef NTKERNEL
+ ExFreePool(Filter->mem);
+ ExFreePool(Filter->Function);
+ ExFreePool(Filter);
+#else
+ free(Filter->mem);
+ free(Filter->Function);
+ free(Filter);
+#endif
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2002
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/** @ingroup NPF
+ * @{
+ */
+
+/** @defgroup NPF_include NPF structures and definitions
+ * @{
+ */
+
+//
+// Registers
+//
+#define EAX 0
+#define ECX 1
+#define EDX 2
+#define EBX 3
+#define ESP 4
+#define EBP 5
+#define ESI 6
+#define EDI 7
+
+#define AX 0
+#define CX 1
+#define DX 2
+#define BX 3
+#define SP 4
+#define BP 5
+#define SI 6
+#define DI 7
+
+#define AL 0
+#define CL 1
+#define DL 2
+#define BL 3
+
+/*! \brief A stream of X86 binary code.*/
+typedef struct binary_stream{
+ INT cur_ip; ///< Current X86 instruction pointer.
+ INT bpf_pc; ///< Current BPF instruction pointer, i.e. position in the BPF program reached by the jitter.
+ PCHAR ibuf; ///< Instruction buffer, contains the X86 generated code.
+ PUINT refs; ///< Jumps reference table.
+}binary_stream;
+
+
+/*! \brief Prototype of a filtering function created by the jitter.
+
+ The syntax and the meaning of the parameters is analogous to the one of bpf_filter(). Notice that the filter
+ is not among the parameters, because it is hardwired in the function.
+*/
+typedef UINT (*BPF_filter_function)( binary_stream *, ULONG, UINT);
+
+/*! \brief Prototype of the emit functions.
+
+ Different emit functions are used to create the reference table and to generate the actual filtering code.
+ This allows to have simpler instruction macros.
+ The first parameter is the stream that will receive the data. The secon one is a variable containing
+ the data, the third one is the length, that can be 1,2 or 4 since it is possible to emit a byte, a short
+ or a work at a time.
+*/
+typedef void (*emit_func)(binary_stream *stream, ULONG value, UINT n);
+
+/*! \brief Structure describing a x86 filtering program created by the jitter.*/
+typedef struct JIT_BPF_Filter{
+ BPF_filter_function Function; ///< The x86 filtering binary, in the form of a BPF_filter_function.
+ PINT mem;
+}
+JIT_BPF_Filter;
+
+
+
+
+/**************************/
+/* X86 INSTRUCTION MACROS */
+/**************************/
+
+/// mov r32,i32
+#define MOVid(r32, i32) \
+ emitm(&stream, 11 << 4 | 1 << 3 | r32 & 0x7, 1); emitm(&stream, i32, 4);
+
+/// mov dr32,sr32
+#define MOVrd(dr32, sr32) \
+ emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// mov dr32,sr32[off]
+#define MOVodd(dr32, sr32, off) \
+ emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
+ emitm(&stream, 1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\
+ emitm(&stream, off, 1);
+
+/// mov dr32,sr32[or32]
+#define MOVobd(dr32, sr32, or32) \
+ emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
+ emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\
+ emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
+
+/// mov dr16,sr32[or32]
+#define MOVobw(dr32, sr32, or32) \
+ emitm(&stream, 0x66, 1); \
+ emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
+ emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\
+ emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
+
+/// mov dr8,sr32[or32]
+#define MOVobb(dr8, sr32, or32) \
+ emitm(&stream, 0x8a, 1); \
+ emitm(&stream, (dr8 & 0x7) << 3 | 4 , 1);\
+ emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
+
+/// mov [dr32][or32],sr32
+#define MOVomd(dr32, or32, sr32) \
+ emitm(&stream, 0x89, 1); \
+ emitm(&stream, (sr32 & 0x7) << 3 | 4 , 1);\
+ emitm(&stream, (or32 & 0x7) << 3 | (dr32 & 0x7) , 1);
+
+/// bswap dr32
+#define BSWAP(dr32) \
+ emitm(&stream, 0xf, 1); \
+ emitm(&stream, 0x19 << 3 | dr32 , 1);
+
+/// xchg al,ah
+#define SWAP_AX() \
+ emitm(&stream, 0x86, 1); \
+ emitm(&stream, 0xc4 , 1);
+
+/// push r32
+#define PUSH(r32) \
+ emitm(&stream, 5 << 4 | 0 << 3 | r32 & 0x7, 1);
+
+/// pop r32
+#define POP(r32) \
+ emitm(&stream, 5 << 4 | 1 << 3 | r32 & 0x7, 1);
+
+/// ret
+#define RET() \
+ emitm(&stream, 12 << 4 | 0 << 3 | 3, 1);
+
+/// add dr32,sr32
+#define ADDrd(dr32, sr32) \
+ emitm(&stream, 0x03, 1);\
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
+
+/// add eax,i32
+#define ADD_EAXi(i32) \
+ emitm(&stream, 0x05, 1);\
+ emitm(&stream, i32, 4);
+
+/// add r32,i32
+#define ADDid(r32, i32) \
+ emitm(&stream, 0x81, 1);\
+ emitm(&stream, 24 << 3 | r32, 1);\
+ emitm(&stream, i32, 4);
+
+/// add r32,i8
+#define ADDib(r32, i8) \
+ emitm(&stream, 0x83, 1);\
+ emitm(&stream, 24 << 3 | r32, 1);\
+ emitm(&stream, i8, 1);
+
+/// sub dr32,sr32
+#define SUBrd(dr32, sr32) \
+ emitm(&stream, 0x2b, 1);\
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
+
+/// sub eax,i32
+#define SUB_EAXi(i32) \
+ emitm(&stream, 0x2d, 1);\
+ emitm(&stream, i32, 4);
+
+/// mul r32
+#define MULrd(r32) \
+ emitm(&stream, 0xf7, 1);\
+ emitm(&stream, 7 << 5 | (r32 & 0x7), 1);
+
+/// div r32
+#define DIVrd(r32) \
+ emitm(&stream, 0xf7, 1);\
+ emitm(&stream, 15 << 4 | (r32 & 0x7), 1);
+
+/// and r8,i8
+#define ANDib(r8, i8) \
+ emitm(&stream, 0x80, 1);\
+ emitm(&stream, 7 << 5 | r8, 1);\
+ emitm(&stream, i8, 1);
+
+/// and r32,i32
+#define ANDid(r32, i32) \
+ if (r32 == EAX){ \
+ emitm(&stream, 0x25, 1);\
+ emitm(&stream, i32, 4);}\
+ else{ \
+ emitm(&stream, 0x81, 1);\
+ emitm(&stream, 7 << 5 | r32, 1);\
+ emitm(&stream, i32, 4);}
+
+/// and dr32,sr32
+#define ANDrd(dr32, sr32) \
+ emitm(&stream, 0x23, 1);\
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// or dr32,sr32
+#define ORrd(dr32, sr32) \
+ emitm(&stream, 0x0b, 1);\
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// or r32,i32
+#define ORid(r32, i32) \
+ if (r32 == EAX){ \
+ emitm(&stream, 0x0d, 1);\
+ emitm(&stream, i32, 4);}\
+ else{ \
+ emitm(&stream, 0x81, 1);\
+ emitm(&stream, 25 << 3 | r32, 1);\
+ emitm(&stream, i32, 4);}
+
+/// shl r32,i8
+#define SHLib(r32, i8) \
+ emitm(&stream, 0xc1, 1);\
+ emitm(&stream, 7 << 5 | r32 & 0x7, 1);\
+ emitm(&stream, i8, 1);
+
+/// shl dr32,cl
+#define SHL_CLrb(dr32) \
+ emitm(&stream, 0xd3, 1);\
+ emitm(&stream, 7 << 5 | dr32 & 0x7, 1);
+
+/// shr r32,i8
+#define SHRib(r32, i8) \
+ emitm(&stream, 0xc1, 1);\
+ emitm(&stream, 29 << 3 | r32 & 0x7, 1);\
+ emitm(&stream, i8, 1);
+
+/// shr dr32,cl
+#define SHR_CLrb(dr32) \
+ emitm(&stream, 0xd3, 1);\
+ emitm(&stream, 29 << 3 | dr32 & 0x7, 1);
+
+/// neg r32
+#define NEGd(r32) \
+ emitm(&stream, 0xf7, 1);\
+ emitm(&stream, 27 << 3 | r32 & 0x7, 1);
+
+/// cmp dr32,sr32[off]
+#define CMPodd(dr32, sr32, off) \
+ emitm(&stream, 3 << 4 | 3 | 1 << 3, 1); \
+ emitm(&stream, 1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\
+ emitm(&stream, off, 1);
+
+/// cmp dr32,sr32
+#define CMPrd(dr32, sr32) \
+ emitm(&stream, 0x3b, 1); \
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// cmp dr32,i32
+#define CMPid(dr32, i32) \
+ if (dr32 == EAX){ \
+ emitm(&stream, 0x3d, 1); \
+ emitm(&stream, i32, 4);} \
+ else{ \
+ emitm(&stream, 0x81, 1); \
+ emitm(&stream, 0x1f << 3 | (dr32 & 0x7), 1);\
+ emitm(&stream, i32, 4);}
+
+/// jne off32
+#define JNEb(off8) \
+ emitm(&stream, 0x75, 1);\
+ emitm(&stream, off8, 1);
+
+/// je off32
+#define JE(off32) \
+ emitm(&stream, 0x0f, 1);\
+ emitm(&stream, 0x84, 1);\
+ emitm(&stream, off32, 4);
+
+/// jle off32
+#define JLE(off32) \
+ emitm(&stream, 0x0f, 1);\
+ emitm(&stream, 0x8e, 1);\
+ emitm(&stream, off32, 4);
+
+/// jle off8
+#define JLEb(off8) \
+ emitm(&stream, 0x7e, 1);\
+ emitm(&stream, off8, 1);
+
+/// ja off32
+#define JA(off32) \
+ emitm(&stream, 0x0f, 1);\
+ emitm(&stream, 0x87, 1);\
+ emitm(&stream, off32, 4);
+
+/// jae off32
+#define JAE(off32) \
+ emitm(&stream, 0x0f, 1);\
+ emitm(&stream, 0x83, 1);\
+ emitm(&stream, off32, 4);
+
+/// jg off32
+#define JG(off32) \
+ emitm(&stream, 0x0f, 1);\
+ emitm(&stream, 0x8f, 1);\
+ emitm(&stream, off32, 4);
+
+/// jge off32
+#define JGE(off32) \
+ emitm(&stream, 0x0f, 1);\
+ emitm(&stream, 0x8d, 1);\
+ emitm(&stream, off32, 4);
+
+/// jmp off32
+#define JMP(off32) \
+ emitm(&stream, 0xe9, 1);\
+ emitm(&stream, off32, 4);
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**************************/
+/* Prototypes */
+/**************************/
+
+/** @ingroup NPF
+ * @{
+ */
+
+/** @defgroup NPF_code NPF functions
+ * @{
+ */
+
+/*!
+ \brief BPF jitter, builds an x86 function from a BPF program.
+ \param fp The BPF pseudo-assembly filter that will be translated into x86 code.
+ \param nins Number of instructions of the input filter.
+ \return The JIT_BPF_Filter structure containing the x86 filtering binary.
+
+ BPF_jitter allocates the buffers for the new native filter and then translates the program pointed by fp
+ calling BPFtoX86().
+*/
+JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins);
+
+/*!
+ \brief Translates a set of BPF instructions in a set of x86 ones.
+ \param ins Pointer to the BPF instructions that will be translated into x86 code.
+ \param nins Number of instructions to translate.
+ \param mem Memory used by the x86 function to emulate the RAM of the BPF pseudo processor.
+ \return The x86 filtering function.
+
+ This function does the hard work for the JIT compilation. It takes a group of BPF pseudo instructions and
+ through the instruction macros defined in jitter.h it is able to create an function directly executable
+ by NPF.
+*/
+BPF_filter_function BPFtoX86(struct bpf_insn *ins, UINT nins, INT *mem);
+/*!
+ \brief Deletes a filtering function that was previously created by BPF_jitter().
+ \param Filter The filter to destroy.
+
+ This function frees the variuos buffers (code, memory, etc.) associated with a filtering function.
+*/
+void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter);
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
--- /dev/null
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "tme.h"
+#include "memory_t.h"
+
+#ifdef _USE_SW_FUNCS_
+
+int32 SW_LONG_AT(void *b, uint32 c)
+{
+ return ((int32)*((uint8 *)b+c)<<24|
+ (int32)*((uint8 *)b+c+1)<<16|
+ (int32)*((uint8 *)b+c+2)<<8|
+ (int32)*((uint8 *)b+c+3)<<0);
+}
+
+uint32 SW_ULONG_AT(void *b, uint32 c)
+{
+ return ((uint32)*((uint8 *)b+c)<<24|
+ (uint32)*((uint8 *)b+c+1)<<16|
+ (uint32)*((uint8 *)b+c+2)<<8|
+ (uint32)*((uint8 *)b+c+3)<<0);
+}
+
+int16 SW_SHORT_AT(void *b, uint32 os)
+{
+ return ((int16)
+ ((int16)*((uint8 *)b+os+0)<<8|
+ (int16)*((uint8 *)b+os+1)<<0));
+}
+
+uint16 SW_USHORT_AT(void *b, uint32 os)
+{
+ return ((uint16)
+ ((uint16)*((uint8 *)b+os+0)<<8|
+ (uint16)*((uint8 *)b+os+1)<<0));
+}
+
+VOID SW_ULONG_ASSIGN(void *dst, uint32 src)
+{
+ *((uint8*)dst+0)=*((uint8*)&src+3);
+ *((uint8*)dst+1)=*((uint8*)&src+2);
+ *((uint8*)dst+2)=*((uint8*)&src+1);
+ *((uint8*)dst+3)=*((uint8*)&src+0);
+
+}
+
+#endif /*_USE_SW_FUNCS_*/
+
+void assert(void* assert, const char* file, int line, void* msg) { };
--- /dev/null
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __memory_t
+#define __memory_t
+
+#define uint8 UCHAR
+#define int8 CHAR
+#define uint16 USHORT
+#define int16 SHORT
+#define uint32 ULONG
+#define int32 LONG
+#define uint64 ULONGLONG
+#define int64 LONGLONG
+
+/*memory type*/
+typedef struct __MEM_TYPE
+{
+ uint8 *buffer;
+ uint32 size;
+} MEM_TYPE, *PMEM_TYPE;
+
+#define LONG_AT(base,offset) (*(int32*)((uint8*)base+(uint32)offset))
+
+#define ULONG_AT(base,offset) (*(uint32*)((uint8*)base+(uint32)offset))
+
+#define SHORT_AT(base,offset) (*(int16*)((uint8*)base+(uint32)offset))
+
+#define USHORT_AT(base,offset) (*(uint16*)((uint8*)base+(uint32)offset))
+
+#ifdef __GNUC__
+#define __inline inline
+#define _USE_SW_FUNCS_
+#endif
+
+#ifdef _USE_SW_FUNCS_
+
+inline int32 SW_LONG_AT(void *b, uint32 c);
+inline uint32 SW_ULONG_AT(void *b, uint32 c);
+inline int16 SW_SHORT_AT(void *b, uint32 os);
+inline uint16 SW_USHORT_AT(void *b, uint32 os);
+inline VOID SW_ULONG_ASSIGN(void *dst, uint32 src);
+
+#else /*_USE_SW_FUNCS_*/
+
+__inline int32 SW_LONG_AT(void *b, uint32 c)
+{
+ return ((int32)*((uint8 *)b+c)<<24|
+ (int32)*((uint8 *)b+c+1)<<16|
+ (int32)*((uint8 *)b+c+2)<<8|
+ (int32)*((uint8 *)b+c+3)<<0);
+}
+
+__inline uint32 SW_ULONG_AT(void *b, uint32 c)
+{
+ return ((uint32)*((uint8 *)b+c)<<24|
+ (uint32)*((uint8 *)b+c+1)<<16|
+ (uint32)*((uint8 *)b+c+2)<<8|
+ (uint32)*((uint8 *)b+c+3)<<0);
+}
+
+__inline int16 SW_SHORT_AT(void *b, uint32 os)
+{
+ return ((int16)
+ ((int16)*((uint8 *)b+os+0)<<8|
+ (int16)*((uint8 *)b+os+1)<<0));
+}
+
+__inline uint16 SW_USHORT_AT(void *b, uint32 os)
+{
+ return ((uint16)
+ ((uint16)*((uint8 *)b+os+0)<<8|
+ (uint16)*((uint8 *)b+os+1)<<0));
+}
+
+__inline VOID SW_ULONG_ASSIGN(void *dst, uint32 src)
+{
+ *((uint8*)dst+0)=*((uint8*)&src+3);
+ *((uint8*)dst+1)=*((uint8*)&src+2);
+ *((uint8*)dst+2)=*((uint8*)&src+1);
+ *((uint8*)dst+3)=*((uint8*)&src+0);
+
+}
+
+#endif /*_USE_SW_FUNCS_*/
+
+#ifdef WIN_NT_DRIVER
+
+#define ALLOCATE_MEMORY(dest,type,amount) \
+ (dest)=ExAllocatePool(NonPagedPool,sizeof(type)*(amount));
+#define ALLOCATE_ZERO_MEMORY(dest,type,amount) \
+ { \
+ (dest)=ExAllocatePool(NonPagedPool,sizeof(type)*(amount)); \
+ if ((dest)!=NULL) \
+ RtlZeroMemory((dest),sizeof(type)*(amount)); \
+ }
+
+#define FREE_MEMORY(dest) ExFreePool(dest);
+#define ZERO_MEMORY(dest,amount) RtlZeroMemory(dest,amount);
+#define COPY_MEMORY(dest,src,amount) RtlCopyMemory(dest,src,amount);
+
+#endif /*WIN_NT_DRIVER*/
+
+
+#endif
+
--- /dev/null
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "normal_lookup.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/tme/normal_lookup.h>
+#else
+#include <tme/tme.h>
+#include <tme/normal_lookup.h>
+#endif
+
+#endif
+
+
+/* lookup in the table, seen as an hash */
+/* if not found, inserts an element */
+/* returns TME_TRUE if the entry is found or created, */
+/* returns TME_FALSE if no more blocks are available */
+uint32 normal_lut_w_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
+{
+ uint32 i;
+ uint32 tocs=0;
+ uint32 *key32=(uint32*) key;
+ uint32 shrinked_key=0;
+ uint32 index;
+ RECORD *records=(RECORD*)data->lut_base_address;
+ uint8 *offset;
+ uint32 key_len=data->key_len;
+ /*the key is shrinked into a 32-bit value */
+ for (i=0; i<key_len;i++)
+ shrinked_key^=key32[i];
+ /*the first index in the table is calculated*/
+ index=shrinked_key % data->lut_entries;
+
+ while (tocs<=data->filled_entries)
+ {
+
+ if (records[index].block==0)
+ { /*creation of a new entry*/
+
+ if (data->filled_blocks==data->shared_memory_blocks)
+ {
+ /*no more free blocks*/
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
+ data->last_found=NULL;
+ return TME_FALSE;
+ }
+
+ /*offset=absolute pointer to the block associated*/
+ /*with the newly created entry*/
+ offset=data->shared_memory_base_address+
+ data->block_size*data->filled_blocks;
+
+ /*copy the key in the block*/
+ COPY_MEMORY(offset,key32,key_len*4);
+ GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
+ /*assign the block relative offset to the entry, in NBO*/
+ SW_ULONG_ASSIGN(&records[index].block,offset-mem_ex->buffer);
+
+ data->filled_blocks++;
+
+ /*assign the exec function ID to the entry, in NBO*/
+ SW_ULONG_ASSIGN(&records[index].exec_fcn,data->default_exec);
+ data->filled_entries++;
+
+ data->last_found=(uint8*)&records[index];
+
+ return TME_TRUE;
+ }
+ /*offset contains the absolute pointer to the block*/
+ /*associated with the current entry */
+ offset=mem_ex->buffer+SW_ULONG_AT(&records[index].block,0);
+
+ for (i=0; (i<key_len) && (key32[i]==ULONG_AT(offset,i*4)); i++);
+
+ if (i==key_len)
+ {
+ /*key in the block matches the one provided, right entry*/
+ GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
+ data->last_found=(uint8*)&records[index];
+ return TME_TRUE;
+ }
+ else
+ {
+ /* wrong entry, rehashing */
+ if (IS_DELETABLE(offset+key_len*4,data))
+ {
+ ZERO_MEMORY(offset,data->block_size);
+ COPY_MEMORY(offset,key32,key_len*4);
+ SW_ULONG_ASSIGN(&records[index].exec_fcn,data->default_exec);
+ GET_TIME((struct timeval*)(offset+key_len*4),time_ref);
+ data->last_found=(uint8*)&records[index];
+ return TME_TRUE;
+ }
+ else
+ {
+ index=(index+data->rehashing_value) % data->lut_entries;
+ tocs++;
+ }
+ }
+ }
+
+ /* nothing found, last found= out of lut */
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
+ data->last_found=NULL;
+ return TME_FALSE;
+
+}
+
+/* lookup in the table, seen as an hash */
+/* if not found, returns out of count entry index */
+/* returns TME_TRUE if the entry is found */
+/* returns TME_FALSE if the entry is not found */
+uint32 normal_lut_wo_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
+{
+ uint32 i;
+ uint32 tocs=0;
+ uint32 *key32=(uint32*) key;
+ uint32 shrinked_key=0;
+ uint32 index;
+ RECORD *records=(RECORD*)data->lut_base_address;
+ uint8 *offset;
+ uint32 key_len=data->key_len;
+ /*the key is shrinked into a 32-bit value */
+ for (i=0; i<key_len;i++)
+ shrinked_key^=key32[i];
+ /*the first index in the table is calculated*/
+ index=shrinked_key % data->lut_entries;
+
+ while (tocs<=data->filled_entries)
+ {
+
+ if (records[index].block==0)
+ { /*out of table, insertion is not allowed*/
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
+ data->last_found=NULL;
+ return TME_FALSE;
+ }
+ /*offset contains the absolute pointer to the block*/
+ /*associated with the current entry */
+
+ offset=mem_ex->buffer+SW_ULONG_AT(&records[index].block,0);
+
+ for (i=0; (i<key_len) && (key32[i]==ULONG_AT(offset,i*4)); i++);
+
+ if (i==key_len)
+ {
+ /*key in the block matches the one provided, right entry*/
+ GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
+ data->last_found=(uint8*)&records[index];
+ return TME_TRUE;
+ }
+ else
+ {
+ /*wrong entry, rehashing*/
+ index=(index+data->rehashing_value) % data->lut_entries;
+ tocs++;
+ }
+ }
+
+ /*nothing found, last found= out of lut*/
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
+ data->last_found=NULL;
+ return TME_FALSE;
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __normal_lookup
+#define __normal_lookup
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+
+#define NORMAL_LUT_W_INSERT 0x00000000
+uint32 normal_lut_w_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
+#define NORMAL_LUT_WO_INSERT 0x00000001
+uint32 normal_lut_wo_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
+#define DUMMY_INSERT 1234
+
+#endif
\ No newline at end of file
--- /dev/null
+; packet capture driver - ReactOS Operating System
+
+LIBRARY PACKET.SYS
+
+EXPORTS
+DriverEntry@8
+
+; EOF
--- /dev/null
+; PACKET.SYS - PACKET protocol driver
+
+LIBRARY packet.sys
+
+EXPORTS
+DriverEntry=DriverEntry@8
+
+; EOF
--- /dev/null
+//#include "resource.h"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 3,0,0,13
+ PRODUCTVERSION 3,0,0,13
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x3L
+ FILESUBTYPE 0x7L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "Comments", "Netgroup Packet Filter Driver\0"
+ VALUE "CompanyName", "Politecnico di Torino\0"
+ VALUE "FileDescription", "NPF Driver - TME extensions\0"
+ VALUE "FileVersion", "3, 0, 0, 13\0"
+ VALUE "InternalName", "NPF + TME \0"
+ VALUE "LegalCopyright", "Copyright © 2002\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "NPF.RC\0"
+ VALUE "PrivateBuild", "REACTOS PRIVATE BUILD\0"
+ VALUE "ProductName", "NPF Driver\0"
+ VALUE "ProductVersion", "3, 0, 0, 13\0"
+ VALUE "SpecialBuild", "Beta testing use only\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
+
+/////////////////////////////////////////////////////////////////////////////
+
+
--- /dev/null
+#ifndef __NTDDPACKET
+#define __NTDDPACKET 1
+
+#ifdef _MSC_VER
+#include "devioctl.h"
+/*#include <packon.h> */
+#else
+#endif
+
+struct _PACKET_OID_DATA {
+ ULONG Oid;
+ ULONG Length;
+ UCHAR Data[1];
+};
+
+typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA;
+
+/*#include <packoff.h> */
+#define FILE_DEVICE_PROTOCOL 0x8000
+#define IOCTL_PROTOCOL_QUERY_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 0 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_SET_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 1 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_STATISTICS CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_RESET CTL_CODE(FILE_DEVICE_PROTOCOL, 3 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_READ CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_WRITE CTL_CODE(FILE_DEVICE_PROTOCOL, 5 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_MACNAME CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_OPEN CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_CLOSE CTL_CODE(FILE_DEVICE_PROTOCOL, 8 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 1999, 2000
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef _MSC_VER
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+#else
+#include <ddk/ntddk.h>
+#include <net/ndis.h>
+#endif
+#include "debug.h"
+#include "packet.h"
+
+static NDIS_MEDIUM MediumArray[] = {
+ NdisMedium802_3,
+ NdisMediumWan,
+ NdisMediumFddi,
+ NdisMediumArcnet878_2,
+ NdisMediumAtm,
+ NdisMedium802_5
+};
+
+#define NUM_NDIS_MEDIA (sizeof MediumArray / sizeof MediumArray[0])
+
+ULONG NamedEventsCounter=0;
+
+//Itoa. Replaces the buggy RtlIntegerToUnicodeString
+void PacketItoa(UINT n,PUCHAR buf){
+int i;
+
+ for(i=0;i<20;i+=2){
+ buf[18-i]=(n%10)+48;
+ buf[19-i]=0;
+ n/=10;
+ }
+
+}
+
+/// Global start time. Used as an absolute reference for timestamp conversion.
+struct time_conv G_Start_Time = {
+ 0,
+ {0, 0},
+};
+
+UINT n_Opened_Instances = 0;
+
+NDIS_SPIN_LOCK Opened_Instances_Lock;
+
+//-------------------------------------------------------------------
+
+NTSTATUS STDCALL
+NPF_Open(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+
+ PDEVICE_EXTENSION DeviceExtension;
+
+ POPEN_INSTANCE Open;
+
+ PIO_STACK_LOCATION IrpSp;
+
+ NDIS_STATUS Status;
+ NDIS_STATUS ErrorStatus;
+ UINT i;
+ PUCHAR tpointer;
+ PLIST_ENTRY PacketListEntry;
+ PCHAR EvName;
+
+ IF_LOUD(DbgPrint("NPF: OpenAdapter\n");)
+
+ DeviceExtension = DeviceObject->DeviceExtension;
+
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ // allocate some memory for the open structure
+#define NPF_TAG_OPENSTRUCT TAG('0', 'O', 'W', 'A')
+ Open=ExAllocatePoolWithTag(NonPagedPool, sizeof(OPEN_INSTANCE), NPF_TAG_OPENSTRUCT);
+
+
+ if (Open==NULL) {
+ // no memory
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory(
+ Open,
+ sizeof(OPEN_INSTANCE)
+ );
+
+
+#define NPF_TAG_EVNAME TAG('1', 'O', 'W', 'A')
+ EvName=ExAllocatePoolWithTag(NonPagedPool, sizeof(L"\\BaseNamedObjects\\NPF0000000000"), NPF_TAG_EVNAME);
+
+ if (EvName==NULL) {
+ // no memory
+ ExFreePool(Open);
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ // Save or open here
+ IrpSp->FileObject->FsContext=Open;
+
+ Open->DeviceExtension=DeviceExtension;
+
+
+ // Save the Irp here for the completeion routine to retrieve
+ Open->OpenCloseIrp=Irp;
+
+ // Allocate a packet pool for our xmit and receive packets
+ NdisAllocatePacketPool(
+ &Status,
+ &Open->PacketPool,
+ TRANSMIT_PACKETS,
+ sizeof(PACKET_RESERVED));
+
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ IF_LOUD(DbgPrint("NPF: Failed to allocate packet pool\n");)
+
+ ExFreePool(Open);
+ ExFreePool(EvName);
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+
+ RtlCopyBytes(EvName,L"\\BaseNamedObjects\\NPF0000000000",sizeof(L"\\BaseNamedObjects\\NPF0000000000"));
+
+ //Create the string containing the name of the read event
+ RtlInitUnicodeString(&Open->ReadEventName,(PCWSTR) EvName);
+
+ PacketItoa(NamedEventsCounter,(PUCHAR)(Open->ReadEventName.Buffer+21));
+
+ InterlockedIncrement(&NamedEventsCounter);
+
+ IF_LOUD(DbgPrint("\nCreated the named event for the read; name=%ws, counter=%d\n", Open->ReadEventName.Buffer,NamedEventsCounter-1);)
+
+ //allocate the event objects
+ Open->ReadEvent=IoCreateNotificationEvent(&Open->ReadEventName,&Open->ReadEventHandle);
+ if(Open->ReadEvent==NULL){
+ ExFreePool(Open);
+ ExFreePool(EvName);
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ KeInitializeEvent(Open->ReadEvent, NotificationEvent, FALSE);
+ KeClearEvent(Open->ReadEvent);
+ NdisInitializeEvent(&Open->WriteEvent);
+ NdisInitializeEvent(&Open->IOEvent);
+ NdisInitializeEvent(&Open->DumpEvent);
+ NdisInitializeEvent(&Open->IOEvent);
+ NdisAllocateSpinLock(&Open->machine_lock);
+
+
+ // list to hold irp's want to reset the adapter
+ InitializeListHead(&Open->ResetIrpList);
+
+
+ // Initialize the request list
+ KeInitializeSpinLock(&Open->RequestSpinLock);
+ InitializeListHead(&Open->RequestList);
+
+ // Initializes the extended memory of the NPF machine
+#define NPF_TAG_MACHINE TAG('2', 'O', 'W', 'A')
+ Open->mem_ex.buffer = ExAllocatePoolWithTag(NonPagedPool, DEFAULT_MEM_EX_SIZE, NPF_TAG_MACHINE);
+ if((Open->mem_ex.buffer) == NULL)
+ {
+ // no memory
+ ExFreePool(Open);
+ ExFreePool(EvName);
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ Open->mem_ex.size = DEFAULT_MEM_EX_SIZE;
+ RtlZeroMemory(Open->mem_ex.buffer, DEFAULT_MEM_EX_SIZE);
+
+ //
+ // Initialize the open instance
+ //
+ Open->BufSize = 0;
+ Open->Buffer = NULL;
+ Open->Bhead = 0;
+ Open->Btail = 0;
+ (INT)Open->BLastByte = -1;
+ Open->Dropped = 0; //reset the dropped packets counter
+ Open->Received = 0; //reset the received packets counter
+ Open->Accepted = 0; //reset the accepted packets counter
+ Open->bpfprogram = NULL; //reset the filter
+ Open->mode = MODE_CAPT;
+ Open->Nbytes.QuadPart = 0;
+ Open->Npackets.QuadPart = 0;
+ Open->Nwrites = 1;
+ Open->Multiple_Write_Counter = 0;
+ Open->MinToCopy = 0;
+ Open->TimeOut.QuadPart = (LONGLONG)1;
+ Open->Bound = TRUE;
+ Open->DumpFileName.Buffer = NULL;
+ Open->DumpFileHandle = NULL;
+ Open->tme.active = TME_NONE_ACTIVE;
+ Open->DumpLimitReached = FALSE;
+ Open->MaxFrameSize = 0;
+
+ //allocate the spinlock for the statistic counters
+ NdisAllocateSpinLock(&Open->CountersLock);
+
+ //allocate the spinlock for the buffer pointers
+ NdisAllocateSpinLock(&Open->BufLock);
+
+ //
+ // link up the request stored in our open block
+ //
+ for (i=0;i<MAX_REQUESTS;i++) {
+ ExInterlockedInsertTailList(
+ &Open->RequestList,
+ &Open->Requests[i].ListElement,
+ &Open->RequestSpinLock);
+
+ }
+
+
+ IoMarkIrpPending(Irp);
+
+ //
+ // Try to open the MAC
+ //
+ IF_LOUD(DbgPrint("NPF: Openinig the device %ws, BindingContext=%d\n",DeviceExtension->AdapterName.Buffer, Open);)
+
+ NdisOpenAdapter(
+ &Status,
+ &ErrorStatus,
+ &Open->AdapterHandle,
+ &Open->Medium,
+ MediumArray,
+ NUM_NDIS_MEDIA,
+ DeviceExtension->NdisProtocolHandle,
+ Open,
+ &DeviceExtension->AdapterName,
+ 0,
+ NULL);
+
+ IF_LOUD(DbgPrint("NPF: Opened the device, Status=%x\n",Status);)
+
+ if (Status != NDIS_STATUS_PENDING)
+ {
+ NPF_OpenAdapterComplete(Open,Status,NDIS_STATUS_SUCCESS);
+ }
+
+ return(STATUS_PENDING);
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_OpenAdapterComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN NDIS_STATUS OpenErrorStatus)
+{
+
+ PIRP Irp;
+ POPEN_INSTANCE Open;
+ PLIST_ENTRY RequestListEntry;
+ PINTERNAL_REQUEST MaxSizeReq;
+ NDIS_STATUS ReqStatus;
+
+
+ IF_LOUD(DbgPrint("NPF: OpenAdapterComplete\n");)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+ //
+ // get the open irp
+ //
+ Irp=Open->OpenCloseIrp;
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ IF_LOUD(DbgPrint("NPF: OpenAdapterComplete-FAILURE\n");)
+
+ NdisFreePacketPool(Open->PacketPool);
+
+ //free mem_ex
+ Open->mem_ex.size = 0;
+ if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
+
+ ExFreePool(Open->ReadEventName.Buffer);
+
+ ZwClose(Open->ReadEventHandle);
+
+
+ ExFreePool(Open);
+ }
+ else {
+ NdisAcquireSpinLock(&Opened_Instances_Lock);
+ n_Opened_Instances++;
+ NdisReleaseSpinLock(&Opened_Instances_Lock);
+
+ IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
+
+ // Get the absolute value of the system boot time.
+ // This is used for timestamp conversion.
+ TIME_SYNCHRONIZE(&G_Start_Time);
+
+ // Extract a request from the list of free ones
+ RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList, &Open->RequestSpinLock);
+
+ if (RequestListEntry == NULL)
+ {
+
+ Open->MaxFrameSize = 1514; // Assume Ethernet
+
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return;
+ }
+
+ MaxSizeReq = CONTAINING_RECORD(RequestListEntry, INTERNAL_REQUEST, ListElement);
+ MaxSizeReq->Irp = Irp;
+ MaxSizeReq->Internal = TRUE;
+
+
+ MaxSizeReq->Request.RequestType = NdisRequestQueryInformation;
+ MaxSizeReq->Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;
+
+
+ MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBuffer = &Open->MaxFrameSize;
+ MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
+
+ // submit the request
+ NdisRequest(
+ &ReqStatus,
+ Open->AdapterHandle,
+ &MaxSizeReq->Request);
+
+
+ if (ReqStatus != NDIS_STATUS_PENDING) {
+ NPF_RequestComplete(Open, &MaxSizeReq->Request, ReqStatus);
+ }
+
+ return;
+
+ }
+
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return;
+
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS STDCALL
+NPF_Close(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+{
+
+ POPEN_INSTANCE Open;
+ NDIS_STATUS Status;
+ PIO_STACK_LOCATION IrpSp;
+ LARGE_INTEGER ThreadDelay;
+
+ IF_LOUD(DbgPrint("NPF: CloseAdapter\n");)
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ Open=IrpSp->FileObject->FsContext;
+
+ // Reset the buffer size. This tells the dump thread to stop.
+ Open->BufSize = 0;
+
+ if( Open->Bound == FALSE){
+
+ NdisWaitEvent(&Open->IOEvent,10000);
+
+ // Free the filter if it's present
+ if(Open->bpfprogram != NULL)
+ ExFreePool(Open->bpfprogram);
+
+ // Free the jitted filter if it's present
+ if(Open->Filter != NULL)
+ BPF_Destroy_JIT_Filter(Open->Filter);
+
+ //free the buffer
+ Open->BufSize=0;
+ if(Open->Buffer != NULL)ExFreePool(Open->Buffer);
+
+ //free mem_ex
+ Open->mem_ex.size = 0;
+ if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
+
+ NdisFreePacketPool(Open->PacketPool);
+
+ // Free the string with the name of the dump file
+ if(Open->DumpFileName.Buffer!=NULL)
+ ExFreePool(Open->DumpFileName.Buffer);
+
+ ExFreePool(Open->ReadEventName.Buffer);
+ ExFreePool(Open);
+
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return(STATUS_SUCCESS);
+ }
+
+ // Unfreeze the consumer
+ if(Open->mode & MODE_DUMP)
+ NdisSetEvent(&Open->DumpEvent);
+ else
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ // Save the IRP
+ Open->OpenCloseIrp = Irp;
+
+ IoMarkIrpPending(Irp);
+
+ // If this instance is in dump mode, complete the dump and close the file
+ if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL){
+ NTSTATUS wres;
+
+ ThreadDelay.QuadPart = -50000000;
+ // Wait the completion of the thread
+ wres = KeWaitForSingleObject(Open->DumpThreadObject,
+ UserRequest,
+ KernelMode,
+ TRUE,
+ &ThreadDelay);
+
+ ObDereferenceObject(Open->DumpThreadObject);
+
+
+ // Flush and close the dump file
+ NPF_CloseDumpFile(Open);
+ }
+
+ // Destroy the read Event
+ ZwClose(Open->ReadEventHandle);
+
+ // Close the adapter
+ NdisCloseAdapter(
+ &Status,
+ Open->AdapterHandle
+ );
+
+ if (Status != NDIS_STATUS_PENDING) {
+
+ NPF_CloseAdapterComplete(
+ Open,
+ Status
+ );
+ return STATUS_SUCCESS;
+
+ }
+
+ return(STATUS_PENDING);
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_CloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
+{
+ POPEN_INSTANCE Open;
+ PIRP Irp;
+
+ IF_LOUD(DbgPrint("NPF: CloseAdapterComplete\n");)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+ // free the allocated structures only if the instance is still bound to the adapter
+ if(Open->Bound == TRUE){
+
+ // Free the filter if it's present
+ if(Open->bpfprogram != NULL)
+ ExFreePool(Open->bpfprogram);
+
+ // Free the jitted filter if it's present
+ if(Open->Filter != NULL)
+ BPF_Destroy_JIT_Filter(Open->Filter);
+
+ //free the buffer
+ Open->BufSize = 0;
+ if(Open->Buffer!=NULL)ExFreePool(Open->Buffer);
+
+ //free mem_ex
+ Open->mem_ex.size = 0;
+ if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
+
+ NdisFreePacketPool(Open->PacketPool);
+
+ Irp=Open->OpenCloseIrp;
+
+ // Free the string with the name of the dump file
+ if(Open->DumpFileName.Buffer!=NULL)
+ ExFreePool(Open->DumpFileName.Buffer);
+
+ ExFreePool(Open->ReadEventName.Buffer);
+ ExFreePool(Open);
+
+ // Complete the request only if the instance is still bound to the adapter
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+ else
+ NdisSetEvent(&Open->IOEvent);
+
+ // Decrease the counter of open instances
+ NdisAcquireSpinLock(&Opened_Instances_Lock);
+ n_Opened_Instances--;
+ NdisReleaseSpinLock(&Opened_Instances_Lock);
+
+ IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
+
+ if(n_Opened_Instances == 0){
+ // Force a synchronization at the next NPF_Open().
+ // This hopefully avoids the synchronization issues caused by hibernation or standby.
+ TIME_DESYNCHRONIZE(&G_Start_Time);
+ }
+
+ return;
+
+}
+//-------------------------------------------------------------------
+
+#ifdef NDIS50
+NDIS_STATUS
+NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent)
+{
+ IF_LOUD(DbgPrint("NPF: PowerChange\n");)
+
+ TIME_DESYNCHRONIZE(&G_Start_Time);
+
+ TIME_SYNCHRONIZE(&G_Start_Time);
+
+ return STATUS_SUCCESS;
+}
+#endif
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_BindAdapter(
+ OUT PNDIS_STATUS Status,
+ IN NDIS_HANDLE BindContext,
+ IN PNDIS_STRING DeviceName,
+ IN PVOID SystemSpecific1,
+ IN PVOID SystemSpecific2
+ )
+{
+ IF_LOUD(DbgPrint("NPF: NPF_BindAdapter\n");)
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_UnbindAdapter(
+ OUT PNDIS_STATUS Status,
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_HANDLE UnbindContext
+ )
+{
+ POPEN_INSTANCE Open =(POPEN_INSTANCE)ProtocolBindingContext;
+ NDIS_STATUS lStatus;
+
+ IF_LOUD(DbgPrint("NPF: NPF_UnbindAdapter\n");)
+
+ // Reset the buffer size. This tells the dump thread to stop.
+ Open->BufSize=0;
+
+ NdisResetEvent(&Open->IOEvent);
+
+ // This open instance is no more bound to the adapter, set Bound to False
+ InterlockedExchange( (PLONG) &Open->Bound, FALSE );
+
+ // Awake a possible pending read on this instance
+ if(Open->mode & MODE_DUMP)
+ NdisSetEvent(&Open->DumpEvent);
+ else
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ // If this instance is in dump mode, complete the dump and close the file
+ if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL)
+ NPF_CloseDumpFile(Open);
+
+ // Destroy the read Event
+ ZwClose(Open->ReadEventHandle);
+
+ // close the adapter
+ NdisCloseAdapter(
+ &lStatus,
+ Open->AdapterHandle
+ );
+
+ if (lStatus != NDIS_STATUS_PENDING) {
+
+ NPF_CloseAdapterComplete(
+ Open,
+ lStatus
+ );
+
+ *Status = NDIS_STATUS_SUCCESS;
+ return;
+
+ }
+
+ *Status = NDIS_STATUS_SUCCESS;
+ return;
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_ResetComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
+
+{
+ POPEN_INSTANCE Open;
+ PIRP Irp;
+
+ PLIST_ENTRY ResetListEntry;
+
+ IF_LOUD(DbgPrint("NPF: PacketResetComplte\n");)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+
+ //
+ // remove the reset IRP from the list
+ //
+ ResetListEntry=ExInterlockedRemoveHeadList(
+ &Open->ResetIrpList,
+ &Open->RequestSpinLock
+ );
+
+#if DBG
+ if (ResetListEntry == NULL) {
+ DbgBreakPoint();
+ return;
+ }
+#endif
+
+ Irp=CONTAINING_RECORD(ResetListEntry,IRP,Tail.Overlay.ListEntry);
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ IF_LOUD(DbgPrint("NPF: PacketResetComplte exit\n");)
+
+ return;
+
+}
--- /dev/null
+/*
+ * Copyright (c) 1999, 2000
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef _MSC_VER
+#include "stdarg.h"
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+#else
+#include <ddk/ntddk.h>
+#include <net/ndis.h>
+#endif
+
+#include "ntddpack.h"
+
+#include "debug.h"
+#include "packet.h"
+#include "win_bpf.h"
+#include "win_bpf_filter_init.h"
+
+#include "tme.h"
+
+#if DBG
+// Declare the global debug flag for this driver.
+//ULONG PacketDebugFlag = PACKET_DEBUG_LOUD;
+ULONG PacketDebugFlag = PACKET_DEBUG_LOUD + PACKET_DEBUG_VERY_LOUD + PACKET_DEBUG_INIT;
+
+#endif
+
+PDEVICE_EXTENSION GlobalDeviceExtension;
+
+////////////////////////////////////////////////////////////////////////////////
+#define ROBERTS_PATCH
+#ifdef ROBERTS_PATCH
+
+#define NDIS_STRING_CONST(x) {sizeof(L##x)-2, sizeof(L##x), L##x}
+
+//void __moddi3(void) {}
+//void __divdi3(void) {}
+
+#endif // ROBERTS_PATCH
+////////////////////////////////////////////////////////////////////////////////
+//
+// Global strings
+//
+NDIS_STRING NPF_Prefix = NDIS_STRING_CONST("NPF_");
+NDIS_STRING devicePrefix = NDIS_STRING_CONST("\\Device\\");
+NDIS_STRING symbolicLinkPrefix = NDIS_STRING_CONST("\\DosDevices\\");
+NDIS_STRING tcpLinkageKeyName = NDIS_STRING_CONST("\\Registry\\Machine\\System"
+ L"\\CurrentControlSet\\Services\\Tcpip\\Linkage");
+NDIS_STRING AdapterListKey = NDIS_STRING_CONST("\\Registry\\Machine\\System"
+ L"\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
+NDIS_STRING bindValueName = NDIS_STRING_CONST("Bind");
+
+
+/// Global variable that points to the names of the bound adapters
+WCHAR* bindP = NULL;
+
+extern struct time_conv G_Start_Time; // from openclos.c
+
+extern NDIS_SPIN_LOCK Opened_Instances_Lock;
+
+//
+// Packet Driver's entry routine.
+//
+NTSTATUS
+#ifdef __GNUC__
+STDCALL
+#endif
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+{
+
+ NDIS_PROTOCOL_CHARACTERISTICS ProtocolChar;
+ UNICODE_STRING MacDriverName;
+ UNICODE_STRING UnicodeDeviceName;
+ PDEVICE_OBJECT DeviceObject = NULL;
+ PDEVICE_EXTENSION DeviceExtension = NULL;
+ NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS ErrorCode = STATUS_SUCCESS;
+ NDIS_STRING ProtoName = NDIS_STRING_CONST("PacketDriver");
+ ULONG DevicesCreated=0;
+ PWSTR BindString;
+ PWSTR ExportString;
+ PWSTR BindStringSave;
+ PWSTR ExportStringSave;
+ NDIS_HANDLE NdisProtocolHandle;
+ WCHAR* bindT;
+ PKEY_VALUE_PARTIAL_INFORMATION tcpBindingsP;
+ UNICODE_STRING macName;
+
+ // This driver at the moment works only on single processor machines
+ if(NdisSystemProcessorCount() != 1){
+ return STATUS_IMAGE_MP_UP_MISMATCH;
+ }
+
+ IF_LOUD(DbgPrint("Packet: DriverEntry\n");)
+
+ RtlZeroMemory(&ProtocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
+
+#ifdef NDIS50
+ ProtocolChar.MajorNdisVersion = 5;
+#else
+ ProtocolChar.MajorNdisVersion = 3;
+#endif
+ ProtocolChar.MinorNdisVersion = 0;
+#ifndef __GNUC__
+ ProtocolChar.Reserved = 0;
+#else
+ ProtocolChar.u1.Reserved = 0;
+#endif
+ ProtocolChar.OpenAdapterCompleteHandler = NPF_OpenAdapterComplete;
+ ProtocolChar.CloseAdapterCompleteHandler = NPF_CloseAdapterComplete;
+#ifndef __GNUC__
+ ProtocolChar.SendCompleteHandler = NPF_SendComplete;
+ ProtocolChar.TransferDataCompleteHandler = NPF_TransferDataComplete;
+#else
+ ProtocolChar.u2.SendCompleteHandler = NPF_SendComplete;
+ ProtocolChar.u3.TransferDataCompleteHandler = NPF_TransferDataComplete;
+#endif
+ ProtocolChar.ResetCompleteHandler = NPF_ResetComplete;
+ ProtocolChar.RequestCompleteHandler = NPF_RequestComplete;
+#ifndef __GNUC__
+ ProtocolChar.ReceiveHandler = NPF_tap;
+#else
+ ProtocolChar.u4.ReceiveHandler = NPF_tap;
+#endif
+ ProtocolChar.ReceiveCompleteHandler = NPF_ReceiveComplete;
+ ProtocolChar.StatusHandler = NPF_Status;
+ ProtocolChar.StatusCompleteHandler = NPF_StatusComplete;
+#ifdef NDIS50
+ ProtocolChar.BindAdapterHandler = NPF_BindAdapter;
+ ProtocolChar.UnbindAdapterHandler = NPF_UnbindAdapter;
+ ProtocolChar.PnPEventHandler = NPF_PowerChange;
+ ProtocolChar.ReceivePacketHandler = NULL;
+#endif
+ ProtocolChar.Name = ProtoName;
+
+ NdisRegisterProtocol(
+ &Status,
+ &NdisProtocolHandle,
+ &ProtocolChar,
+ sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ IF_LOUD(DbgPrint("NPF: Failed to register protocol with NDIS\n");)
+
+ return Status;
+
+ }
+
+ NdisAllocateSpinLock(&Opened_Instances_Lock);
+
+ // Set up the device driver entry points.
+ DriverObject->MajorFunction[IRP_MJ_CREATE] = NPF_Open;
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] = NPF_Close;
+ DriverObject->MajorFunction[IRP_MJ_READ] = NPF_Read;
+ DriverObject->MajorFunction[IRP_MJ_WRITE] = NPF_Write;
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NPF_IoControl;
+ DriverObject->DriverUnload = NPF_Unload;
+
+/*
+ // Get the name of the Packet driver and the name of the NIC driver
+ // to bind to from the registry
+ Status=NPF_ReadRegistry(
+ &BindString,
+ &ExportString,
+ RegistryPath
+ );
+
+ if (Status != STATUS_SUCCESS) {
+
+ IF_LOUD(DbgPrint("Trying dynamic binding\n");)
+ */
+ bindP = getAdaptersList();
+
+ if (bindP == NULL) {
+ IF_LOUD(DbgPrint("Adapters not found in the registry, try to copy the bindings of TCP-IP.\n");)
+
+ tcpBindingsP = getTcpBindings();
+
+ if (tcpBindingsP == NULL){
+ IF_LOUD(DbgPrint("TCP-IP not found, quitting.\n");)
+ goto RegistryError;
+ }
+
+ bindP = (WCHAR*)tcpBindingsP;
+ bindT = (WCHAR*)(tcpBindingsP->Data);
+ } else {
+ bindT = bindP;
+ }
+
+ for (; *bindT != UNICODE_NULL; bindT += (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR)) {
+ RtlInitUnicodeString(&macName, bindT);
+ createDevice(DriverObject, &macName, NdisProtocolHandle);
+ }
+
+ return STATUS_SUCCESS;
+/*
+ }
+ BindStringSave = BindString;
+ ExportStringSave = ExportString;
+ //
+ // create a device object for each entry
+ //
+ while (*BindString!= UNICODE_NULL && *ExportString!= UNICODE_NULL) {
+ //
+ // Create a counted unicode string for both null terminated strings
+ //
+ RtlInitUnicodeString(
+ &MacDriverName,
+ BindString);
+ RtlInitUnicodeString(
+ &UnicodeDeviceName,
+ ExportString);
+ //
+ // Advance to the next string of the MULTI_SZ string
+ //
+ BindString += (MacDriverName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR);
+ ExportString += (UnicodeDeviceName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR);
+ IF_LOUD(DbgPrint("NPF: DeviceName=%ws MacName=%ws\n",UnicodeDeviceName.Buffer,MacDriverName.Buffer);)
+ //
+ // Create the device object
+ //
+ Status = IoCreateDevice(
+ DriverObject,
+ sizeof(DEVICE_EXTENSION),
+ &UnicodeDeviceName,
+ FILE_DEVICE_PROTOCOL,
+ 0,
+ FALSE,
+ &DeviceObject);
+ if (Status != STATUS_SUCCESS) {
+ IF_LOUD(DbgPrint("NPF: IoCreateDevice() failed:\n");)
+ break;
+ }
+ DevicesCreated++;
+ DeviceObject->Flags |= DO_DIRECT_IO;
+ DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
+ DeviceExtension->DeviceObject = DeviceObject;
+ //
+ // Save the the name of the MAC driver to open in the Device Extension
+ //
+ DeviceExtension->AdapterName=MacDriverName;
+ if (DevicesCreated == 1) {
+ DeviceExtension->BindString = NULL;
+ DeviceExtension->ExportString = NULL;
+ }
+ DeviceExtension->NdisProtocolHandle=NdisProtocolHandle;
+ }
+ if (DevicesCreated > 0) {
+ //
+ // Managed to create at least one device.
+ //
+ IF_LOUD(DbgPrint("NPF: Managed to create at least one device.\n");)
+ return STATUS_SUCCESS;
+ }
+ ExFreePool(BindStringSave);
+ ExFreePool(ExportStringSave);
+ */
+
+RegistryError:
+ IF_LOUD(DbgPrint("NPF: RegistryError: calling NdisDeregisterProtocol()\n");)
+ NdisDeregisterProtocol(
+ &Status,
+ NdisProtocolHandle
+ );
+
+ Status=STATUS_UNSUCCESSFUL;
+
+ return(Status);
+
+}
+
+//-------------------------------------------------------------------
+
+PWCHAR getAdaptersList(void)
+{
+ PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
+ OBJECT_ATTRIBUTES objAttrs;
+ NTSTATUS status;
+ HANDLE keyHandle;
+ UINT BufPos=0;
+
+#define NPF_TAG_DEVICENAME TAG('0', 'P', 'W', 'A')
+ PWCHAR DeviceNames = (PWCHAR) ExAllocatePoolWithTag(PagedPool, 4096, NPF_TAG_DEVICENAME);
+
+ if (DeviceNames == NULL) {
+ IF_LOUD(DbgPrint("Unable the allocate the buffer for the list of the network adapters\n");)
+ return NULL;
+ }
+
+ InitializeObjectAttributes(&objAttrs, &AdapterListKey,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+ status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
+ if (!NT_SUCCESS(status)) {
+
+ //IF_LOUD(DbgPrint("Status of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
+ IF_LOUD(DbgPrint("Status of %x opening %ws\n", status, AdapterListKey.Buffer);)
+
+ } else { //OK
+ ULONG resultLength;
+ KEY_VALUE_PARTIAL_INFORMATION valueInfo;
+ CHAR AdapInfo[1024];
+ UINT i=0;
+
+ IF_LOUD(DbgPrint("getAdaptersList: scanning the list of the adapters in the registry, DeviceNames=%x\n",DeviceNames);)
+
+ // Scan the list of the devices
+ while((status=ZwEnumerateKey(keyHandle,i,KeyBasicInformation,AdapInfo,sizeof(AdapInfo),&resultLength))==STATUS_SUCCESS) {
+ WCHAR ExportKeyName [512];
+ PWCHAR ExportKeyPrefix = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
+ UINT ExportKeyPrefixSize = sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
+ PWCHAR LinkageKeyPrefix = L"\\Linkage";
+ UINT LinkageKeyPrefixSize = sizeof(L"\\Linkage");
+ NDIS_STRING FinalExportKey = NDIS_STRING_CONST("Export");
+ PKEY_BASIC_INFORMATION tInfo= (PKEY_BASIC_INFORMATION)AdapInfo;
+ UNICODE_STRING AdapterKeyName;
+ HANDLE ExportKeyHandle;
+ KEY_VALUE_PARTIAL_INFORMATION valueInfo;
+ ULONG resultLength;
+
+ RtlCopyMemory(ExportKeyName,
+ ExportKeyPrefix,
+ ExportKeyPrefixSize);
+
+ RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize,
+ tInfo->Name,
+ tInfo->NameLength+2);
+
+ RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize+tInfo->NameLength,
+ LinkageKeyPrefix,
+ LinkageKeyPrefixSize);
+
+ IF_LOUD(DbgPrint("Key name=%ws\n", ExportKeyName);)
+
+ RtlInitUnicodeString(&AdapterKeyName, ExportKeyName);
+
+ InitializeObjectAttributes(&objAttrs, &AdapterKeyName,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ status=ZwOpenKey(&ExportKeyHandle,KEY_READ,&objAttrs);
+
+ if (!NT_SUCCESS(status)) {
+ DbgPrint("OpenKey Failed, %d!\n",status);
+ i++;
+ continue;
+ }
+
+ status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
+ KeyValuePartialInformation, &valueInfo,
+ sizeof(valueInfo), &resultLength);
+
+ if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
+ IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
+ } else { // We know how big it needs to be.
+ ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
+#define NPF_TAG_KEYVALUE TAG('1', 'P', 'W', 'A')
+ PKEY_VALUE_PARTIAL_INFORMATION valueInfoP = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePoolWithTag(PagedPool, valueInfoLength, NPF_TAG_KEYVALUE);
+ if (valueInfoP != NULL) {
+ status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
+ KeyValuePartialInformation,
+ valueInfoP,
+ valueInfoLength, &resultLength);
+ if (!NT_SUCCESS(status)) {
+ IF_LOUD(DbgPrint("Status of %x querying key value\n", status);)
+ } else {
+ IF_LOUD(DbgPrint("Device %d = %ws\n", i, valueInfoP->Data);)
+ RtlCopyMemory((PCHAR)DeviceNames+BufPos,
+ valueInfoP->Data,
+ valueInfoP->DataLength);
+ BufPos+=valueInfoP->DataLength-2;
+ }
+
+ ExFreePool(valueInfoP);
+ } else {
+ IF_LOUD(DbgPrint("Error Allocating the buffer for the device name\n");)
+ }
+
+ }
+
+ // terminate the buffer
+ DeviceNames[BufPos/2]=0;
+ DeviceNames[BufPos/2+1]=0;
+
+ ZwClose (ExportKeyHandle);
+ i++;
+
+ }
+
+ ZwClose (keyHandle);
+
+ }
+ if(BufPos==0){
+ ExFreePool(DeviceNames);
+ return NULL;
+ }
+ return DeviceNames;
+}
+
+//-------------------------------------------------------------------
+
+PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(void)
+{
+ PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
+ OBJECT_ATTRIBUTES objAttrs;
+ NTSTATUS status;
+ HANDLE keyHandle;
+
+ InitializeObjectAttributes(&objAttrs, &tcpLinkageKeyName,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+ status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
+ if (!NT_SUCCESS(status)) {
+ IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
+ } else {
+ ULONG resultLength;
+ KEY_VALUE_PARTIAL_INFORMATION valueInfo;
+
+ IF_LOUD(DbgPrint("\n\nOpened %ws\n", tcpLinkageKeyName.Buffer);)
+
+ status = ZwQueryValueKey(keyHandle, &bindValueName,
+ KeyValuePartialInformation, &valueInfo,
+ sizeof(valueInfo), &resultLength);
+ if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
+ IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
+ } else { // We know how big it needs to be.
+ ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
+#define NPF_TAG_KEYVALUE2 TAG('2', 'P', 'W', 'A')
+ PKEY_VALUE_PARTIAL_INFORMATION valueInfoP =
+ (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, valueInfoLength, NPF_TAG_KEYVALUE2);
+
+ if (valueInfoP != NULL) {
+ status = ZwQueryValueKey(keyHandle, &bindValueName,
+ KeyValuePartialInformation,
+ valueInfoP,
+ valueInfoLength, &resultLength);
+
+ if (!NT_SUCCESS(status)) {
+ IF_LOUD(DbgPrint("\n\nStatus of %x querying key value\n", status);)
+ }
+ else if (valueInfoLength != resultLength) {
+ IF_LOUD(DbgPrint("\n\nQuerying key value result len = %u "
+ "but previous len = %u\n",
+ resultLength, valueInfoLength);)
+ }
+ else if (valueInfoP->Type != REG_MULTI_SZ) {
+ IF_LOUD(DbgPrint("\n\nTcpip bind value not REG_MULTI_SZ but %u\n",
+ valueInfoP->Type);)
+ }
+ else { // It's OK
+#if DBG
+ ULONG i;
+ WCHAR* dataP = (WCHAR*)(&valueInfoP->Data[0]);
+ IF_LOUD(DbgPrint("\n\nBind value:\n");)
+ for (i = 0; *dataP != UNICODE_NULL; i++) {
+ UNICODE_STRING macName;
+ RtlInitUnicodeString(&macName, dataP);
+ IF_LOUD(DbgPrint("\n\nMac %u = %ws\n", i, macName.Buffer);)
+ dataP +=
+ (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
+ }
+#endif // DBG
+ result = valueInfoP;
+ }
+ }
+ }
+ ZwClose(keyHandle);
+ }
+ return result;
+}
+
+//-------------------------------------------------------------------
+
+BOOLEAN createDevice(IN OUT PDRIVER_OBJECT adriverObjectP,
+ IN PUNICODE_STRING amacNameP, NDIS_HANDLE aProtoHandle)
+{
+ NTSTATUS status;
+ PDEVICE_OBJECT devObjP;
+ UNICODE_STRING deviceName;
+ UNICODE_STRING deviceSymLink;
+
+ IF_LOUD(DbgPrint("\n\ncreateDevice for MAC %ws\n", amacNameP->Buffer););
+ if (RtlCompareMemory(amacNameP->Buffer, devicePrefix.Buffer,
+ devicePrefix.Length) < devicePrefix.Length) {
+ return FALSE;
+ }
+
+ deviceName.Length = 0;
+ deviceName.MaximumLength = (USHORT)(amacNameP->Length + NPF_Prefix.Length + sizeof(UNICODE_NULL));
+#define NPF_TAG_DEVICENAMEBUF TAG('3', 'P', 'W', 'A')
+ deviceName.Buffer = ExAllocatePoolWithTag(PagedPool, deviceName.MaximumLength, NPF_TAG_DEVICENAMEBUF);
+
+ if (deviceName.Buffer == NULL)
+ return FALSE;
+
+ deviceSymLink.Length = 0;
+ deviceSymLink.MaximumLength =(USHORT)(amacNameP->Length-devicePrefix.Length
+ + symbolicLinkPrefix.Length
+ + NPF_Prefix.Length
+ + sizeof(UNICODE_NULL));
+
+#define NPF_TAG_SYMLINKBUF TAG('3', 'P', 'W', 'A')
+ deviceSymLink.Buffer = ExAllocatePoolWithTag(NonPagedPool, deviceSymLink.MaximumLength, NPF_TAG_SYMLINKBUF);
+
+ if (deviceSymLink.Buffer == NULL)
+ {
+ ExFreePool(deviceName.Buffer);
+ return FALSE;
+ }
+
+ RtlAppendUnicodeStringToString(&deviceName, &devicePrefix);
+ RtlAppendUnicodeStringToString(&deviceName, &NPF_Prefix);
+ RtlAppendUnicodeToString(&deviceName, amacNameP->Buffer +
+ devicePrefix.Length / sizeof(WCHAR));
+
+ RtlAppendUnicodeStringToString(&deviceSymLink, &symbolicLinkPrefix);
+ RtlAppendUnicodeStringToString(&deviceSymLink, &NPF_Prefix);
+ RtlAppendUnicodeToString(&deviceSymLink, amacNameP->Buffer +
+ devicePrefix.Length / sizeof(WCHAR));
+
+ IF_LOUD(DbgPrint("Creating device name: %ws\n", deviceName.Buffer);)
+
+ status = IoCreateDevice(adriverObjectP,
+ sizeof(PDEVICE_EXTENSION),
+ &deviceName,
+ FILE_DEVICE_TRANSPORT,
+ 0,
+ FALSE,
+ &devObjP);
+
+ if (NT_SUCCESS(status)) {
+ PDEVICE_EXTENSION devExtP = (PDEVICE_EXTENSION)devObjP->DeviceExtension;
+
+ IF_LOUD(DbgPrint("Device created successfully\n"););
+
+ devObjP->Flags |= DO_DIRECT_IO;
+ RtlInitUnicodeString(&devExtP->AdapterName,amacNameP->Buffer);
+ devExtP->NdisProtocolHandle=aProtoHandle;
+
+ IF_LOUD(DbgPrint("Trying to create SymLink %ws\n",deviceSymLink.Buffer););
+
+ if (IoCreateSymbolicLink(&deviceSymLink,&deviceName) != STATUS_SUCCESS) {
+ IF_LOUD(DbgPrint("\n\nError creating SymLink %ws\nn", deviceSymLink.Buffer););
+
+ ExFreePool(deviceName.Buffer);
+ ExFreePool(deviceSymLink.Buffer);
+
+ devExtP->ExportString = NULL;
+
+ return FALSE;
+ }
+
+ IF_LOUD(DbgPrint("SymLink %ws successfully created.\n\n", deviceSymLink.Buffer););
+
+ devExtP->ExportString = deviceSymLink.Buffer;
+
+ ExFreePool(deviceName.Buffer);
+
+ return TRUE;
+ }
+
+ else
+ {
+ IF_LOUD(DbgPrint("\n\nIoCreateDevice status = %x\n", status););
+
+ ExFreePool(deviceName.Buffer);
+ ExFreePool(deviceSymLink.Buffer);
+
+ return FALSE;
+ }
+}
+
+//-------------------------------------------------------------------
+
+VOID STDCALL
+NPF_Unload(IN PDRIVER_OBJECT DriverObject)
+{
+ PDEVICE_OBJECT DeviceObject;
+ PDEVICE_OBJECT OldDeviceObject;
+ PDEVICE_EXTENSION DeviceExtension;
+
+ NDIS_HANDLE NdisProtocolHandle;
+ NDIS_STATUS Status;
+
+ NDIS_STRING SymLink;
+
+ IF_LOUD(DbgPrint("NPF: Unload\n"););
+
+ DeviceObject = DriverObject->DeviceObject;
+
+ while (DeviceObject != NULL) {
+ OldDeviceObject=DeviceObject;
+
+ DeviceObject=DeviceObject->NextDevice;
+
+ DeviceExtension = OldDeviceObject->DeviceExtension;
+
+ NdisProtocolHandle=DeviceExtension->NdisProtocolHandle;
+
+ IF_LOUD(DbgPrint("Deleting Adapter %ws, Protocol Handle=%x, Device Obj=%x (%x)\n",
+ DeviceExtension->AdapterName.Buffer,
+ NdisProtocolHandle,
+ DeviceObject,
+ OldDeviceObject););
+
+ if (DeviceExtension->ExportString)
+ {
+ RtlInitUnicodeString(&SymLink , DeviceExtension->ExportString);
+
+ IF_LOUD(DbgPrint("Deleting SymLink at %p\n", SymLink.Buffer););
+
+ IoDeleteSymbolicLink(&SymLink);
+ ExFreePool(DeviceExtension->ExportString);
+ }
+
+ IoDeleteDevice(OldDeviceObject);
+ }
+
+ NdisDeregisterProtocol(
+ &Status,
+ NdisProtocolHandle
+ );
+
+ // Free the adapters names
+ ExFreePool( bindP );
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS STDCALL
+NPF_IoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+{
+ POPEN_INSTANCE Open;
+ PIO_STACK_LOCATION IrpSp;
+ PLIST_ENTRY RequestListEntry;
+ PINTERNAL_REQUEST pRequest;
+ ULONG FunctionCode;
+ NDIS_STATUS Status;
+ PLIST_ENTRY PacketListEntry;
+ UINT i;
+ PUCHAR tpointer;
+ ULONG dim,timeout;
+ PUCHAR prog;
+ PPACKET_OID_DATA OidData;
+ int *StatsBuf;
+ PNDIS_PACKET pPacket;
+ ULONG mode;
+ PWSTR DumpNameBuff;
+ PUCHAR TmpBPFProgram;
+ INT WriteRes;
+ BOOLEAN SyncWrite = FALSE;
+ struct bpf_insn *initprogram;
+ ULONG insns;
+ ULONG cnt;
+ BOOLEAN IsExtendedFilter=FALSE;
+
+ IF_LOUD(DbgPrint("NPF: IoControl\n");)
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
+ Open=IrpSp->FileObject->FsContext;
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+
+ IF_LOUD(DbgPrint("NPF: Function code is %08lx buff size=%08lx %08lx\n",FunctionCode,IrpSp->Parameters.DeviceIoControl.InputBufferLength,IrpSp->Parameters.DeviceIoControl.OutputBufferLength);)
+
+
+ switch (FunctionCode){
+
+ case BIOCGSTATS: //function to get the capture stats
+
+ if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 4*sizeof(INT)){
+ EXIT_FAILURE(0);
+ }
+
+ *(((PUINT)Irp->UserBuffer)+3) = Open->Accepted;
+ *(((PUINT)Irp->UserBuffer)) = Open->Received;
+ *(((PUINT)Irp->UserBuffer)+1) = Open->Dropped;
+ *(((PUINT)Irp->UserBuffer)+2) = 0; // Not yet supported
+
+ EXIT_SUCCESS(4*sizeof(INT));
+
+ break;
+
+ case BIOCGEVNAME: //function to get the name of the event associated with the current instance
+
+ if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength<26){
+ EXIT_FAILURE(0);
+ }
+
+ RtlCopyMemory(Irp->UserBuffer,(Open->ReadEventName.Buffer)+18,26);
+
+ EXIT_SUCCESS(26);
+
+ break;
+
+ case BIOCSENDPACKETSSYNC:
+
+ SyncWrite = TRUE;
+
+ case BIOCSENDPACKETSNOSYNC:
+
+ WriteRes = NPF_BufferedWrite(Irp,
+ (PUCHAR)Irp->AssociatedIrp.SystemBuffer,
+ IrpSp->Parameters.DeviceIoControl.InputBufferLength,
+ SyncWrite);
+
+ if( WriteRes != -1)
+ {
+ EXIT_SUCCESS(WriteRes);
+ }
+
+ EXIT_FAILURE(WriteRes);
+
+ break;
+
+ case BIOCSETF:
+
+ // Free the previous buffer if it was present
+ if(Open->bpfprogram!=NULL){
+ TmpBPFProgram=Open->bpfprogram;
+ Open->bpfprogram = NULL;
+ ExFreePool(TmpBPFProgram);
+ }
+
+ if (Open->Filter!=NULL)
+ {
+ JIT_BPF_Filter *OldFilter=Open->Filter;
+ Open->Filter=NULL;
+ BPF_Destroy_JIT_Filter(OldFilter);
+ }
+
+ // Get the pointer to the new program
+ prog=(PUCHAR)Irp->AssociatedIrp.SystemBuffer;
+
+ if(prog==NULL){
+ IF_LOUD(DbgPrint("0001");)
+
+ EXIT_FAILURE(0);
+ }
+
+ insns=(IrpSp->Parameters.DeviceIoControl.InputBufferLength)/sizeof(struct bpf_insn);
+
+ //count the number of operative instructions
+ for (cnt=0;(cnt<insns) &&(((struct bpf_insn*)prog)[cnt].code!=BPF_SEPARATION); cnt++);
+
+ IF_LOUD(DbgPrint("Operative instructions=%u\n",cnt);)
+
+ if (((struct bpf_insn*)prog)[cnt].code==BPF_SEPARATION && (insns-cnt-1)!=0)
+ {
+ IF_LOUD(DbgPrint("Initialization instructions=%u\n",insns-cnt-1);)
+
+ IsExtendedFilter=TRUE;
+
+ initprogram=&((struct bpf_insn*)prog)[cnt+1];
+
+ if(bpf_filter_init(initprogram,&(Open->mem_ex),&(Open->tme), &G_Start_Time)!=INIT_OK)
+ {
+
+ IF_LOUD(DbgPrint("Error initializing NPF machine (bpf_filter_init)\n");)
+
+ EXIT_FAILURE(0);
+ }
+ }
+
+ //the NPF processor has been initialized, we have to validate the operative instructions
+ insns=cnt;
+
+ if(bpf_validate((struct bpf_insn*)prog,cnt,Open->mem_ex.size)==0)
+ {
+ IF_LOUD(DbgPrint("Error validating program");)
+ //FIXME: the machine has been initialized(?), but the operative code is wrong.
+ //we have to reset the machine!
+ //something like: reallocate the mem_ex, and reset the tme_core
+ EXIT_FAILURE(0);
+ }
+
+ // Allocate the memory to contain the new filter program
+ // We could need the original BPF binary if we are forced to use bpf_filter_with_2_buffers()
+#define NPF_TAG_BPFPROG TAG('4', 'P', 'W', 'A')
+ TmpBPFProgram=(PUCHAR)ExAllocatePoolWithTag(NonPagedPool, cnt*sizeof(struct bpf_insn), NPF_TAG_BPFPROG);
+ if (TmpBPFProgram==NULL){
+ IF_LOUD(DbgPrint("Error - No memory for filter");)
+ // no memory
+ EXIT_FAILURE(0);
+ }
+
+ //copy the program in the new buffer
+ RtlCopyMemory(TmpBPFProgram,prog,cnt*sizeof(struct bpf_insn));
+ Open->bpfprogram=TmpBPFProgram;
+
+ // Create the new JIT filter function
+ if(!IsExtendedFilter)
+ if((Open->Filter=BPF_jitter((struct bpf_insn*)Open->bpfprogram,cnt)) == NULL) {
+ IF_LOUD(DbgPrint("Error jittering filter");)
+ EXIT_FAILURE(0);
+ }
+
+ //return
+ Open->Bhead = 0;
+ Open->Btail = 0;
+ (INT)Open->BLastByte = -1;
+ Open->Received = 0;
+ Open->Dropped = 0;
+ Open->Accepted = 0;
+
+ EXIT_SUCCESS(IrpSp->Parameters.DeviceIoControl.InputBufferLength);
+
+ break;
+
+ case BIOCSMODE: //set the capture mode
+
+ mode=*((PULONG)Irp->AssociatedIrp.SystemBuffer);
+
+ if(mode == MODE_CAPT){
+ Open->mode=MODE_CAPT;
+
+ EXIT_SUCCESS(0);
+ }
+ else if (mode==MODE_MON){
+ Open->mode=MODE_MON;
+
+ EXIT_SUCCESS(0);
+ }
+ else{
+ if(mode & MODE_STAT){
+ Open->mode = MODE_STAT;
+ Open->Nbytes.QuadPart=0;
+ Open->Npackets.QuadPart=0;
+
+ if(Open->TimeOut.QuadPart==0)Open->TimeOut.QuadPart=-10000000;
+
+ }
+
+ if(mode & MODE_DUMP){
+
+ Open->mode |= MODE_DUMP;
+ Open->MinToCopy=(Open->BufSize<2000000)?Open->BufSize/2:1000000;
+
+ }
+ EXIT_SUCCESS(0);
+ }
+
+ EXIT_FAILURE(0);
+
+ break;
+
+ case BIOCSETDUMPFILENAME:
+
+ if(Open->mode & MODE_DUMP)
+ {
+
+ // Close current dump file
+ if(Open->DumpFileHandle != NULL){
+ NPF_CloseDumpFile(Open);
+ Open->DumpFileHandle = NULL;
+ }
+
+ if(IrpSp->Parameters.DeviceIoControl.InputBufferLength == 0){
+ EXIT_FAILURE(0);
+ }
+
+ // Allocate the buffer that will contain the string
+#define NPF_TAG_DUMPNAMEBUF TAG('5', 'P', 'W', 'A')
+ DumpNameBuff=ExAllocatePoolWithTag(NonPagedPool, IrpSp->Parameters.DeviceIoControl.InputBufferLength, NPF_TAG_DUMPNAMEBUF);
+ if(DumpNameBuff==NULL || Open->DumpFileName.Buffer!=NULL){
+ IF_LOUD(DbgPrint("NPF: unable to allocate the dump filename: not enough memory or name already set\n");)
+ EXIT_FAILURE(0);
+ }
+
+ // Copy the buffer
+ RtlCopyBytes((PVOID)DumpNameBuff,
+ Irp->AssociatedIrp.SystemBuffer,
+ IrpSp->Parameters.DeviceIoControl.InputBufferLength);
+
+ // Force a \0 at the end of the filename to avoid that malformed strings cause RtlInitUnicodeString to crash the system
+ ((SHORT*)DumpNameBuff)[IrpSp->Parameters.DeviceIoControl.InputBufferLength/2-1]=0;
+
+ // Create the unicode string
+ RtlInitUnicodeString(&Open->DumpFileName, DumpNameBuff);
+
+ IF_LOUD(DbgPrint("NPF: dump file name set to %ws, len=%d\n",
+ Open->DumpFileName.Buffer,
+ IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
+
+ // Try to create the file
+ if ( NT_SUCCESS( NPF_OpenDumpFile(Open,&Open->DumpFileName,FALSE)) &&
+ NT_SUCCESS( NPF_StartDump(Open))){
+
+ EXIT_SUCCESS(0);
+ }
+ }
+
+ EXIT_FAILURE(0);
+
+ break;
+
+ case BIOCSETDUMPLIMITS:
+
+ Open->MaxDumpBytes = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
+ Open->MaxDumpPacks = *((PULONG)Irp->AssociatedIrp.SystemBuffer + 1);
+
+ IF_LOUD(DbgPrint("NPF: Set dump limits to %u bytes, %u packs\n", Open->MaxDumpBytes, Open->MaxDumpPacks);)
+
+ EXIT_SUCCESS(0);
+
+ break;
+
+ case BIOCISDUMPENDED:
+ if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 4){
+ EXIT_FAILURE(0);
+ }
+
+ *((UINT*)Irp->UserBuffer) = (Open->DumpLimitReached)?1:0;
+
+ EXIT_SUCCESS(4);
+
+ break;
+
+ case BIOCSETBUFFERSIZE:
+
+ // Get the number of bytes to allocate
+ dim = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+
+ // Free the old buffer
+ tpointer = Open->Buffer;
+ if(tpointer != NULL){
+ Open->BufSize = 0;
+ Open->Buffer = NULL;
+ ExFreePool(tpointer);
+ }
+ // Allocate the new buffer
+ if(dim!=0){
+#define NPF_TAG_TPOINTER TAG('6', 'P', 'W', 'A')
+ tpointer = ExAllocatePoolWithTag(NonPagedPool, dim, NPF_TAG_TPOINTER);
+ if (tpointer==NULL) {
+ // no memory
+ Open->BufSize = 0;
+ Open->Buffer = NULL;
+ EXIT_FAILURE(0);
+ }
+ }
+ else
+ tpointer = NULL;
+
+ Open->Buffer = tpointer;
+ Open->Bhead = 0;
+ Open->Btail = 0;
+ (INT)Open->BLastByte = -1;
+
+ Open->BufSize = (UINT)dim;
+ EXIT_SUCCESS(dim);
+
+ break;
+
+ case BIOCSRTIMEOUT: //set the timeout on the read calls
+
+ timeout = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+ if((int)timeout==-1)
+ Open->TimeOut.QuadPart=(LONGLONG)IMMEDIATE;
+ else {
+ Open->TimeOut.QuadPart=(LONGLONG)timeout;
+ Open->TimeOut.QuadPart*=10000;
+ Open->TimeOut.QuadPart=-Open->TimeOut.QuadPart;
+ }
+
+ //IF_LOUD(DbgPrint("NPF: read timeout set to %d:%d\n",Open->TimeOut.HighPart,Open->TimeOut.LowPart);)
+ EXIT_SUCCESS(timeout);
+
+ break;
+
+ case BIOCSWRITEREP: //set the writes repetition number
+
+ Open->Nwrites = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+
+ EXIT_SUCCESS(Open->Nwrites);
+
+ break;
+
+ case BIOCSMINTOCOPY: //set the minimum buffer's size to copy to the application
+
+ Open->MinToCopy = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+
+ EXIT_SUCCESS(Open->MinToCopy);
+
+ break;
+
+ case IOCTL_PROTOCOL_RESET:
+
+ IF_LOUD(DbgPrint("NPF: IoControl - Reset request\n");)
+
+ IoMarkIrpPending(Irp);
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+
+ ExInterlockedInsertTailList(&Open->ResetIrpList,&Irp->Tail.Overlay.ListEntry,&Open->RequestSpinLock);
+ NdisReset(&Status,Open->AdapterHandle);
+ if (Status != NDIS_STATUS_PENDING) {
+ IF_LOUD(DbgPrint("NPF: IoControl - ResetComplete being called\n");)
+ NPF_ResetComplete(Open,Status);
+ }
+
+ break;
+
+
+ case BIOCSETOID:
+ case BIOCQUERYOID:
+
+ // Extract a request from the list of free ones
+ RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList,&Open->RequestSpinLock);
+ if (RequestListEntry == NULL)
+ {
+ EXIT_FAILURE(0);
+ }
+
+ pRequest=CONTAINING_RECORD(RequestListEntry,INTERNAL_REQUEST,ListElement);
+ pRequest->Irp=Irp;
+ pRequest->Internal = FALSE;
+
+
+ //
+ // See if it is an Ndis request
+ //
+ OidData=Irp->AssociatedIrp.SystemBuffer;
+
+ if (((FunctionCode == BIOCSETOID) || (FunctionCode == BIOCQUERYOID))
+ &&
+ (IrpSp->Parameters.DeviceIoControl.InputBufferLength == IrpSp->Parameters.DeviceIoControl.OutputBufferLength)
+ &&
+ (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA))
+ &&
+ (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length)) {
+
+ IF_LOUD(DbgPrint("NPF: IoControl: Request: Oid=%08lx, Length=%08lx\n",OidData->Oid,OidData->Length);)
+
+ //
+ // The buffer is valid
+ //
+ if (FunctionCode == BIOCSETOID){
+
+ pRequest->Request.RequestType=NdisRequestSetInformation;
+ pRequest->Request.DATA.SET_INFORMATION.Oid=OidData->Oid;
+
+ pRequest->Request.DATA.SET_INFORMATION.InformationBuffer=OidData->Data;
+ pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength=OidData->Length;
+ } else{
+ pRequest->Request.RequestType=NdisRequestQueryInformation;
+ pRequest->Request.DATA.QUERY_INFORMATION.Oid=OidData->Oid;
+
+ pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer=OidData->Data;
+ pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength=OidData->Length;
+
+ }
+
+ NdisResetEvent(&Open->IOEvent);
+ //
+ // submit the request
+ //
+ NdisRequest(
+ &Status,
+ Open->AdapterHandle,
+ &pRequest->Request
+ );
+
+ } else {
+ //
+ // buffer too small
+ //
+ Status=NDIS_STATUS_FAILURE;
+ pRequest->Request.DATA.SET_INFORMATION.BytesRead=0;
+ pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten=0;
+
+ }
+
+ if (Status != NDIS_STATUS_PENDING) {
+ IF_LOUD(DbgPrint("NPF: Calling RequestCompleteHandler\n");)
+
+ NPF_RequestComplete(Open, &pRequest->Request, Status);
+ return Status;
+
+ }
+
+ NdisWaitEvent(&Open->IOEvent, 5000);
+
+ return(Open->IOStatus);
+
+ break;
+
+
+ default:
+
+ EXIT_FAILURE(0);
+ }
+
+ return Status;
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_RequestComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_REQUEST NdisRequest,
+ IN NDIS_STATUS Status
+ )
+
+{
+ POPEN_INSTANCE Open;
+ PIO_STACK_LOCATION IrpSp;
+ PIRP Irp;
+ PINTERNAL_REQUEST pRequest;
+ UINT FunctionCode;
+ KIRQL OldIrq;
+
+ PPACKET_OID_DATA OidData;
+
+ IF_LOUD(DbgPrint("NPF: RequestComplete\n");)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+ pRequest=CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request);
+ Irp=pRequest->Irp;
+
+ if(pRequest->Internal == TRUE){
+
+ // Put the request in the list of the free ones
+ ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
+
+ if(Status != NDIS_STATUS_SUCCESS)
+ Open->MaxFrameSize = 1514; // Assume Ethernet
+
+ // We always return success, because the adapter has been already opened
+ Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return;
+ }
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
+
+ OidData=Irp->AssociatedIrp.SystemBuffer;
+
+ if (FunctionCode == BIOCSETOID) {
+
+ OidData->Length=pRequest->Request.DATA.SET_INFORMATION.BytesRead;
+
+ } else {
+
+ if (FunctionCode == BIOCQUERYOID) {
+
+ OidData->Length=pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten;
+
+ IF_LOUD(DbgPrint("RequestComplete: BytesWritten=%d\n",pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten);)
+ }
+
+ }
+
+ Irp->IoStatus.Information=IrpSp->Parameters.DeviceIoControl.InputBufferLength;
+
+ IF_LOUD(DbgPrint("RequestComplete: BytesReturned=%d\n",IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
+
+ ExInterlockedInsertTailList(
+ &Open->RequestList,
+ &pRequest->ListElement,
+ &Open->RequestSpinLock);
+
+ Irp->IoStatus.Status = Status;
+
+ Open->IOStatus = Status;
+
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ // Unlock the caller
+ NdisSetEvent(&Open->IOEvent);
+
+ return;
+
+
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_Status(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN PVOID StatusBuffer,
+ IN UINT StatusBufferSize
+ )
+
+{
+
+ IF_LOUD(DbgPrint("NPF: Status Indication\n");)
+
+ return;
+
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_StatusComplete(
+ IN NDIS_HANDLE ProtocolBindingContext
+ )
+
+{
+
+ IF_LOUD(DbgPrint("NPF: StatusIndicationComplete\n");)
+
+ return;
+
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_ReadRegistry(
+ IN PWSTR *MacDriverName,
+ IN PWSTR *PacketDriverName,
+ IN PUNICODE_STRING RegistryPath
+ )
+
+{
+ NTSTATUS Status;
+
+ RTL_QUERY_REGISTRY_TABLE ParamTable[4];
+
+ PWSTR Bind = L"Bind";
+ PWSTR Export = L"Export";
+ PWSTR Parameters = L"Parameters";
+ PWSTR Linkage = L"Linkage";
+
+ PWCHAR Path;
+
+#define NPF_TAG_PATH TAG('7', 'P', 'W', 'A')
+ Path=ExAllocatePoolWithTag(PagedPool, RegistryPath->Length+sizeof(WCHAR), NPF_TAG_PATH);
+
+ if (Path == NULL) {
+ IF_LOUD(DbgPrint("\nPacketReadRegistry: returing STATUS_INSUFFICIENT_RESOURCES\n");)
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory(
+ Path,
+ RegistryPath->Length+sizeof(WCHAR)
+ );
+
+ RtlCopyMemory(
+ Path,
+ RegistryPath->Buffer,
+ RegistryPath->Length
+ );
+
+ IF_LOUD(DbgPrint("NPF: Reg path is %ws\n",RegistryPath->Buffer);)
+
+ RtlZeroMemory(
+ ParamTable,
+ sizeof(ParamTable)
+ );
+
+
+
+ //
+ // change to the linkage key
+ //
+ //ParamTable[0].QueryRoutine = NULL;
+ ParamTable[0].QueryRoutine = NPF_QueryRegistryRoutine;
+ ParamTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
+ ParamTable[0].Name = Linkage;
+
+
+ //
+ // Get the name of the mac driver we should bind to
+ //
+
+ ParamTable[1].QueryRoutine = NPF_QueryRegistryRoutine;
+ ParamTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED |
+ RTL_QUERY_REGISTRY_NOEXPAND;
+
+ ParamTable[1].Name = Bind;
+ ParamTable[1].EntryContext = (PVOID)MacDriverName;
+ ParamTable[1].DefaultType = REG_MULTI_SZ;
+
+ //
+ // Get the name that we should use for the driver object
+ //
+
+ ParamTable[2].QueryRoutine = NPF_QueryRegistryRoutine;
+ ParamTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED |
+ RTL_QUERY_REGISTRY_NOEXPAND;
+
+ ParamTable[2].Name = Export;
+ ParamTable[2].EntryContext = (PVOID)PacketDriverName;
+ ParamTable[2].DefaultType = REG_MULTI_SZ;
+
+
+ Status=RtlQueryRegistryValues(
+ RTL_REGISTRY_ABSOLUTE,
+ Path,
+ ParamTable,
+ NULL,
+ NULL
+ );
+
+ if (Status != STATUS_SUCCESS) {
+ // insert hard coded parameters here while registry on ROS is not working...
+ IF_LOUD(DbgPrint("PacketReadRegistry() RtlQueryRegistryValues failed - returing fixed parameters\n");)
+
+ *MacDriverName = ExAllocatePool(PagedPool, 50 * sizeof(WCHAR));
+ //memcpy(*MacDriverName, L"\\Device\\ne2000", 15 * sizeof(WCHAR));
+ memcpy(*MacDriverName, L"\\Device\\ne2000", 15 * sizeof(WCHAR));
+
+ *PacketDriverName = ExAllocatePool(PagedPool, 50 * sizeof(WCHAR));
+ memcpy(*PacketDriverName, L"\\Device\\NPF_ne2000", 19 * sizeof(WCHAR));
+ Status = STATUS_SUCCESS;
+
+ }
+
+ ExFreePool(Path);
+ return Status;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS STDCALL
+NPF_QueryRegistryRoutine(
+ IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext
+ )
+
+{
+
+ PUCHAR Buffer;
+
+ IF_LOUD(DbgPrint("Perf: QueryRegistryRoutine\n");)
+
+ if (ValueType != REG_MULTI_SZ) {
+
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+
+ }
+
+#define NPF_TAG_REGBUF TAG('8', 'P', 'W', 'A')
+ Buffer=ExAllocatePoolWithTag(NonPagedPool, ValueLength, NPF_TAG_REGBUF);
+
+ if (Buffer==NULL) {
+
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ }
+
+ RtlCopyMemory(
+ Buffer,
+ ValueData,
+ ValueLength
+ );
+
+ *((PUCHAR *)EntryContext)=Buffer;
+
+ return STATUS_SUCCESS;
+
+}
--- /dev/null
+/*
+ * Copyright (c) 1999, 2000
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/** @ingroup NPF
+ * @{
+ */
+
+/** @defgroup NPF_include NPF structures and definitions
+ * @{
+ */
+
+#ifndef __PACKET_INCLUDE______
+#define __PACKET_INCLUDE______
+
+#define NTKERNEL ///< Forces the compilation of the jitter with kernel calls
+
+#ifdef __GNUC__
+#undef EXIT_SUCCESS
+#undef EXIT_FAILURE
+#define UNICODE_NULL ((WCHAR)0) // winnt
+#include "win_bpf.h"
+#include <internal/ps.h>
+#endif
+
+#include "jitter.h"
+#include "tme.h"
+
+#define MAX_REQUESTS 32 ///< Maximum number of simultaneous IOCTL requests.
+
+#define Packet_ALIGNMENT sizeof(int) ///< Alignment macro. Defines the alignment size.
+#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1)) ///< Alignment macro. Rounds up to the next
+ ///< even multiple of Packet_ALIGNMENT.
+
+
+/***************************/
+/* IOCTLs */
+/***************************/
+
+/*!
+ \brief IOCTL code: set kernel buffer size.
+
+ This IOCTL is used to set a new size of the circular buffer associated with an instance of NPF.
+ When a BIOCSETBUFFERSIZE command is received, the driver frees the old buffer, allocates the new one
+ and resets all the parameters associated with the buffer in the OPEN_INSTANCE structure. The currently
+ buffered packets are lost.
+*/
+#define BIOCSETBUFFERSIZE 9592
+
+/*!
+ \brief IOCTL code: set packet filtering program.
+
+ This IOCTL sets a new packet filter in the driver. Before allocating any memory for the new filter, the
+ bpf_validate() function is called to check the correctness of the filter. If this function returns TRUE,
+ the filter is copied to the driver's memory, its address is stored in the bpfprogram field of the
+ OPEN_INSTANCE structure associated with current instance of the driver, and the filter will be applied to
+ every incoming packet. This command also empties the circular buffer used by current instance
+ to store packets. This is done to avoid the presence in the buffer of packets that do not match the filter.
+*/
+#define BIOCSETF 9030
+
+/*!
+ \brief IOCTL code: get the capture stats
+
+ This command returns to the application the number of packets received and the number of packets dropped by
+ an instance of the driver.
+*/
+#define BIOCGSTATS 9031
+
+/*!
+ \brief IOCTL code: set the read timeout
+
+ This command sets the maximum timeout after which a read is released, also if no data packets were received.
+*/
+#define BIOCSRTIMEOUT 7416
+
+/*!
+ \brief IOCTL code: set working mode
+
+ This IOCTL can be used to set the working mode of a NPF instance. The new mode, received by the driver in the
+ buffer associated with the IOCTL command, can be #MODE_CAPT for capture mode (the default), #MODE_STAT for
+ statistical mode or #MODE_DUMP for dump mode.
+*/
+#define BIOCSMODE 7412
+
+/*!
+ \brief IOCTL code: set number of physical repetions of every packet written by the app
+
+ Sets the number of times a single write call must be repeated. This command sets the OPEN_INSTANCE::Nwrites
+ member, and is used to implement the 'multiple write' feature of the driver.
+*/
+#define BIOCSWRITEREP 7413
+
+/*!
+ \brief IOCTL code: set minimum amount of data in the kernel buffer that unlocks a read call
+
+ This command sets the OPEN_INSTANCE::MinToCopy member.
+*/
+#define BIOCSMINTOCOPY 7414
+
+/*!
+ \brief IOCTL code: set an OID value
+
+ This IOCTL is used to perform an OID set operation on the NIC driver.
+*/
+#define BIOCSETOID 2147483648UL
+
+/*!
+ \brief IOCTL code: get an OID value
+
+ This IOCTL is used to perform an OID get operation on the NIC driver.
+*/
+#define BIOCQUERYOID 2147483652UL
+
+/*!
+ \brief IOCTL code: set the name of a the file used by kernel dump mode
+
+ This command opens a file whose name is contained in the IOCTL buffer and associates it with current NPf instance.
+ The dump thread uses it to copy the content of the circular buffer to file.
+ If a file was already opened, the driver closes it before opening the new one.
+*/
+#define BIOCSETDUMPFILENAME 9029
+
+/*!
+ \brief IOCTL code: get the name of the event that the driver signals when some data is present in the buffer
+
+ Command used by the application to retrieve the name of the global event associated with a NPF instance.
+ The event is signaled by the driver when the kernel buffer contains enough data for a transfer.
+*/
+#define BIOCGEVNAME 7415
+
+/*!
+ \brief IOCTL code: Send a buffer containing multiple packets to the network, ignoring the timestamps.
+
+ Command used to send a buffer of packets in a single system call. Every packet in the buffer is preceded by
+ a sf_pkthdr structure. The timestamps of the packets are ignored, i.e. the packets are sent as fast as
+ possible. The NPF_BufferedWrite() function is invoked to send the packets.
+*/
+#define BIOCSENDPACKETSNOSYNC 9032
+
+/*!
+ \brief IOCTL code: Send a buffer containing multiple packets to the network, considering the timestamps.
+
+ Command used to send a buffer of packets in a single system call. Every packet in the buffer is preceded by
+ a sf_pkthdr structure. The timestamps of the packets are used to synchronize the write, i.e. the packets
+ are sent to the network respecting the intervals specified in the sf_pkthdr structure assiciated with each
+ packet. NPF_BufferedWrite() function is invoked to send the packets.
+*/
+#define BIOCSENDPACKETSSYNC 9033
+
+/*!
+ \brief IOCTL code: Set the dump file limits.
+
+ This IOCTL sets the limits (maximum size and maximum number of packets) of the dump file created when the
+ driver works in dump mode.
+*/
+#define BIOCSETDUMPLIMITS 9034
+
+/*!
+ \brief IOCTL code: Get the status of the kernel dump process.
+
+ This command returns TRUE if the kernel dump is ended, i.e if one of the limits set with BIOCSETDUMPLIMITS
+ (amount of bytes or number of packets) has been reached.
+*/
+#define BIOCISDUMPENDED 7411
+
+// Working modes
+#define MODE_CAPT 0x0 ///< Capture working mode
+#define MODE_STAT 0x1 ///< Statistical working mode
+#define MODE_MON 0x2 ///< Kernel monitoring mode
+#define MODE_DUMP 0x10 ///< Kernel dump working mode
+
+
+#define IMMEDIATE 1 ///< Immediate timeout. Forces a read call to return immediately.
+
+
+// The following definitions are used to provide compatibility
+// of the dump files with the ones of libpcap
+#define TCPDUMP_MAGIC 0xa1b2c3d4 ///< Libpcap magic number. Used by programs like tcpdump to recognize a driver's generated dump file.
+#define PCAP_VERSION_MAJOR 2 ///< Major libpcap version of the dump file. Used by programs like tcpdump to recognize a driver's generated dump file.
+#define PCAP_VERSION_MINOR 4 ///< Minor libpcap version of the dump file. Used by programs like tcpdump to recognize a driver's generated dump file.
+
+/*!
+ \brief Header of a libpcap dump file.
+
+ Used when a driver instance is set in dump mode to create a libpcap-compatible file.
+*/
+struct packet_file_header
+{
+ UINT magic; ///< Libpcap magic number
+ USHORT version_major; ///< Libpcap major version
+ USHORT version_minor; ///< Libpcap minor version
+ UINT thiszone; ///< Gmt to local correction
+ UINT sigfigs; ///< Accuracy of timestamps
+ UINT snaplen; ///< Length of the max saved portion of each packet
+ UINT linktype; ///< Data link type (DLT_*). See win_bpf.h for details.
+};
+
+/*!
+ \brief Header associated to a packet in the driver's buffer when the driver is in dump mode.
+ Similar to the bpf_hdr structure, but simpler.
+*/
+struct sf_pkthdr {
+ struct timeval ts; ///< time stamp
+ UINT caplen; ///< Length of captured portion. The captured portion can be different from
+ ///< the original packet, because it is possible (with a proper filter) to
+ ///< instruct the driver to capture only a portion of the packets.
+ UINT len; ///< Length of the original packet (off wire).
+};
+
+/*!
+ \brief Stores an OID request.
+
+ This structure is used by the driver to perform OID query or set operations on the underlying NIC driver.
+ The OID operations be performed usually only by network drivers, but NPF exports this mechanism to user-level
+ applications through an IOCTL interface. The driver uses this structure to wrap a NDIS_REQUEST structure.
+ This allows to handle correctly the callback structure of NdisRequest(), handling multiple requests and
+ maintaining information about the IRPs to complete.
+*/
+typedef struct _INTERNAL_REQUEST {
+ LIST_ENTRY ListElement; ///< Used to handle lists of requests.
+ PIRP Irp; ///< Irp that performed the request
+ BOOLEAN Internal; ///< True if the request is for internal use of npf.sys. False if the request is performed by the user through an IOCTL.
+ NDIS_REQUEST Request; ///< The structure with the actual request, that will be passed to NdisRequest().
+} INTERNAL_REQUEST, *PINTERNAL_REQUEST;
+
+/*!
+ \brief Contains a NDIS packet.
+
+ The driver uses this structure to wrap a NDIS_PACKET structure.
+ This allows to handle correctly the callback structure of NdisTransferData(), handling multiple requests and
+ maintaining information about the IRPs to complete.
+*/
+typedef struct _PACKET_RESERVED {
+ LIST_ENTRY ListElement; ///< Used to handle lists of packets.
+ PIRP Irp; ///< Irp that performed the request
+ PMDL pMdl; ///< MDL mapping the buffer of the packet.
+ BOOLEAN FreeBufAfterWrite; ///< True if the memory buffer associated with the packet must be freed
+ ///< after a call to NdisSend().
+} PACKET_RESERVED, *PPACKET_RESERVED;
+
+#define RESERVED(_p) ((PPACKET_RESERVED)((_p)->ProtocolReserved)) ///< Macro to obtain a NDIS_PACKET from a PACKET_RESERVED
+
+/*!
+ \brief Port device extension.
+
+ Structure containing some data relative to every adapter on which NPF is bound.
+*/
+typedef struct _DEVICE_EXTENSION {
+ NDIS_HANDLE NdisProtocolHandle; ///< NDIS handle of NPF.
+ NDIS_STRING AdapterName; ///< Name of the adapter.
+ PWSTR ExportString; ///< Name of the exported device, i.e. name that the applications will use
+ ///< to open this adapter through WinPcap.
+} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+
+/*!
+ \brief Contains the state of a running instance of the NPF driver.
+
+ This is the most important structure of NPF: it is used by almost all the functions of the driver. An
+ _OPEN_INSTANCE structure is associated with every user-level session, allowing concurrent access
+ to the driver.
+*/
+typedef struct _OPEN_INSTANCE
+{
+ PDEVICE_EXTENSION DeviceExtension; ///< Pointer to the _DEVICE_EXTENSION structure of the device on which
+ ///< the instance is bound.
+ NDIS_HANDLE AdapterHandle; ///< NDIS idetifier of the adapter used by this instance.
+ UINT Medium; ///< Type of physical medium the underlying NDIS driver uses. See the
+ ///< documentation of NdisOpenAdapter in the MS DDK for details.
+ NDIS_HANDLE PacketPool; ///< Pool of NDIS_PACKET structures used to transfer the packets from and to the NIC driver.
+ PIRP OpenCloseIrp; ///< Pointer used to store the open/close IRP requests and provide them to the
+ ///< callbacks of NDIS.
+ KSPIN_LOCK RequestSpinLock; ///< SpinLock used to synchronize the OID requests.
+ LIST_ENTRY RequestList; ///< List of pending OID requests.
+ LIST_ENTRY ResetIrpList; ///< List of pending adapter reset requests.
+ INTERNAL_REQUEST Requests[MAX_REQUESTS]; ///< Array of structures that wrap every single OID request.
+ PMDL BufferMdl; ///< Pointer to a Memory descriptor list (MDL) that maps the circular buffer's memory.
+ PKEVENT ReadEvent; ///< Pointer to the event on which the read calls on this instance must wait.
+ HANDLE ReadEventHandle; ///< Handle of the event on which the read calls on this instance must wait.
+ UNICODE_STRING ReadEventName; ///< Name of the event on which the read calls on this instance must wait.
+ ///< The event is created with a name, so it can be used at user level to know when it
+ ///< is possible to access the driver without being blocked. This fiels stores the name
+ ///< that and is used by the BIOCGEVNAME IOCTL call.
+ INT Received; ///< Number of packets received by current instance from its opening, i.e. number of
+ ///< packet received by the network adapter since the beginning of the
+ ///< capture/monitoring/dump session.
+ INT Dropped; ///< Number of packet that current instance had to drop, from its opening. A packet
+ ///< is dropped if there is no more space to store it in the circular buffer that the
+ ///< driver associates to current instance.
+ INT Accepted; ///< Number of packet that current capture instance acepted, from its opening. A packet
+ ///< is accepted if it passes the filter and fits in the buffer. Accepted packets are the
+ ///< ones that reach the application.
+ PUCHAR bpfprogram; ///< Pointer to the filtering pseudo-code associated with current instance of the driver.
+ ///< This code is used only in particular situations (for example when the packet received
+ ///< from the NIC driver is stored in two non-consecutive buffers. In normal situations
+ ///< the filtering routine created by the JIT compiler and pointed by the next field
+ ///< is used. See \ref NPF for details on the filtering process.
+ JIT_BPF_Filter *Filter; ///< Pointer to the native filtering function created by the jitter.
+ ///< See BPF_jitter() for details.
+ PUCHAR Buffer; ///< Pointer to the circular buffer associated with every driver instance. It contains the
+ ///< data that will be passed to the application. See \ref NPF for details.
+ UINT Bhead; ///< Head of the circular buffer.
+ UINT Btail; ///< Tail of the circular buffer.
+ UINT BufSize; ///< Size of the circular buffer.
+ UINT BLastByte; ///< Position of the last valid byte in the circular buffer.
+ PMDL TransferMdl; ///< MDL used to map the portion of the buffer that will contain an incoming packet.
+ ///< Used by NdisTransferData().
+ NDIS_SPIN_LOCK BufLock; ///< SpinLock that protects the access tho the circular buffer variables.
+ UINT MinToCopy; ///< Minimum amount of data in the circular buffer that unlocks a read. Set with the
+ ///< BIOCSMINTOCOPY IOCTL.
+ LARGE_INTEGER TimeOut; ///< Timeout after which a read is released, also if the amount of data in the buffer is
+ ///< less than MinToCopy. Set with the BIOCSRTIMEOUT IOCTL.
+
+ int mode; ///< Working mode of the driver. See PacketSetMode() for details.
+ LARGE_INTEGER Nbytes; ///< Amount of bytes accepted by the filter when this instance is in statistical mode.
+ LARGE_INTEGER Npackets; ///< Number of packets accepted by the filter when this instance is in statistical mode.
+ NDIS_SPIN_LOCK CountersLock; ///< SpinLock that protects the statistical mode counters.
+ UINT Nwrites; ///< Number of times a single write must be physically repeated. See \ref NPF for an
+ ///< explanation
+ UINT Multiple_Write_Counter; ///< Counts the number of times a single write has already physically repeated.
+ NDIS_EVENT WriteEvent; ///< Event used to synchronize the multiple write process.
+ NDIS_EVENT IOEvent; ///< Event used to synchronize I/O requests with the callback structure of NDIS.
+ NDIS_STATUS IOStatus; ///< Maintains the status of and OID request call, that will be passed to the application.
+ BOOLEAN Bound; ///< Specifies if NPF is still bound to the adapter used by this instance. Bound can be
+ ///< FALSE if a Plug and Play adapter has been removed or disabled by the user.
+ HANDLE DumpFileHandle; ///< Handle of the file used in dump mode.
+ PFILE_OBJECT DumpFileObject; ///< Pointer to the object of the file used in dump mode.
+ PKTHREAD DumpThreadObject; ///< Pointer to the object of the thread used in dump mode.
+ HANDLE DumpThreadHandle; ///< Handle of the thread created by dump mode to asynchronously move the buffer to disk.
+ NDIS_EVENT DumpEvent; ///< Event used to synchronize the dump thread with the tap when the instance is in dump mode.
+ LARGE_INTEGER DumpOffset; ///< Current offset in the dump file.
+ UNICODE_STRING DumpFileName; ///< String containing the name of the dump file.
+ UINT MaxDumpBytes; ///< Maximum dimension in bytes of the dump file. If the dump file reaches this size it
+ ///< will be closed. A value of 0 means unlimited size.
+ UINT MaxDumpPacks; ///< Maximum number of packets that will be saved in the dump file. If this number of
+ ///< packets is reached the dump will be closed. A value of 0 means unlimited number of
+ ///< packets.
+ BOOLEAN DumpLimitReached; ///< TRUE if the maximum dimension of the dump file (MaxDumpBytes or MaxDumpPacks) is
+ ///< reached.
+ MEM_TYPE mem_ex; ///< Memory used by the TME virtual co-processor
+ TME_CORE tme; ///< Data structure containing the virtualization of the TME co-processor
+ NDIS_SPIN_LOCK machine_lock; ///< SpinLock that protects the mem_ex buffer
+ UINT MaxFrameSize; ///< Maximum frame size that the underlying MAC acceptes. Used to perform a check on the
+ ///< size of the frames sent with NPF_Write() or NPF_BufferedWrite().
+} OPEN_INSTANCE, *POPEN_INSTANCE;
+
+
+#define TRANSMIT_PACKETS 256 ///< Maximum number of packets in the transmit packet pool. This value is an upper bound to the number
+ ///< of packets that can be transmitted at the same time or with a single call to NdisSendPackets.
+
+
+/// Macro used in the I/O routines to return the control to user-mode with a success status.
+#define EXIT_SUCCESS(quantity) Irp->IoStatus.Information=quantity;\
+ Irp->IoStatus.Status = STATUS_SUCCESS;\
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);\
+ return STATUS_SUCCESS;\
+
+/// Macro used in the I/O routines to return the control to user-mode with a failure status.
+#define EXIT_FAILURE(quantity) Irp->IoStatus.Information=quantity;\
+ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;\
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);\
+ return STATUS_UNSUCCESSFUL;\
+
+/**
+ * @}
+ */
+
+
+/***************************/
+/* Prototypes */
+/***************************/
+
+/** @defgroup NPF_code NPF functions
+ * @{
+ */
+
+
+/*!
+ \brief The initialization routine of the driver.
+ \param DriverObject The driver object of NPF created by the system.
+ \param RegistryPath The registry path containing the keys related to the driver.
+ \return A string containing a list of network adapters.
+
+ DriverEntry is a mandatory function in a device driver. Like the main() of a user level program, it is called
+ by the system when the driver is loaded in memory and started. Its purpose is to initialize the driver,
+ performing all the allocations and the setup. In particular, DriverEntry registers all the driver's I/O
+ callbacks, creates the devices, defines NPF as a protocol inside NDIS.
+*/
+//NTSTATUS
+//DriverEntry(
+// IN PDRIVER_OBJECT DriverObject,
+// IN PUNICODE_STRING RegistryPath
+// );
+
+/*!
+ \brief Returns the list of the MACs available on the system.
+ \return A string containing a list of network adapters.
+
+ The list of adapters is retrieved from the
+ SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318} registry key.
+ NPF tries to create its bindings from this list. In this way it is possible to be loaded
+ and unloaded dynamically without passing from the control panel.
+*/
+PWCHAR getAdaptersList(VOID);
+
+/*!
+ \brief Returns the MACs that bind to TCP/IP.
+ \return Pointer to the registry key containing the list of adapters on which TCP/IP is bound.
+
+ If getAdaptersList() fails, NPF tries to obtain the TCP/IP bindings through this function.
+*/
+PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(VOID);
+
+/*!
+ \brief Creates a device for a given MAC.
+ \param adriverObjectP The driver object that will be associated with the device, i.e. the one of NPF.
+ \param amacNameP The name of the network interface that the device will point.
+ \param aProtoHandle NDIS protocol handle of NPF.
+ \return If the function succeeds, the return value is nonzero.
+
+ NPF creates a device for every valid network adapter. The new device points to the NPF driver, but contains
+ information about the original device. In this way, when the user opens the new device, NPF will be able to
+ determine the correct adapter to use.
+*/
+BOOLEAN createDevice(
+ IN OUT PDRIVER_OBJECT adriverObjectP,
+ IN PUNICODE_STRING amacNameP,
+ NDIS_HANDLE aProtoHandle);
+
+/*!
+ \brief Opens a new instance of the driver.
+ \param DeviceObject Pointer to the device object utilized by the user.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function is called by the OS when a new instance of the driver is opened, i.e. when a user application
+ performs a CreateFile on a device created by NPF. NPF_Open allocates and initializes variables, objects
+ and buffers needed by the new instance, fills the OPEN_INSTANCE structure associated with it and opens the
+ adapter with a call to NdisOpenAdapter.
+*/
+NTSTATUS STDCALL
+NPF_Open(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+/*!
+ \brief Ends the opening of an adapter.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param Status Status of the opening operation performed by NDIS.
+ \param OpenErrorStatus not used by NPF.
+
+ Callback function associated with the NdisOpenAdapter() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished an open operation that was previously started by NPF_Open().
+*/
+VOID
+NPF_OpenAdapterComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN NDIS_STATUS OpenErrorStatus
+ );
+
+/*!
+ \brief Closes an instance of the driver.
+ \param DeviceObject Pointer to the device object utilized by the user.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function is called when a running instance of the driver is closed by the user with a CloseHandle().
+ It stops the capture/monitoring/dump process, deallocates the memory and the objects associated with the
+ instance and closing the files. The network adapter is then closed with a call to NdisCloseAdapter.
+*/
+NTSTATUS STDCALL
+NPF_Close(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+/*!
+ \brief Ends the closing of an adapter.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param Status Status of the close operation performed by NDIS.
+
+ Callback function associated with the NdisCloseAdapter() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished a close operation that was previously started by NPF_Close().
+*/
+VOID
+NPF_CloseAdapterComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status
+ );
+
+/*!
+ \brief Callback invoked by NDIS when a packet arrives from the network.
+ \param ProtocolBindingContext Context of the function. Points to a OPEN_INSTANCE structure that identifies
+ the NPF instance to which the packets are destined.
+ \param MacReceiveContext Handle that identifies the underlying NIC driver that generated the request.
+ This value must be used when the packet is transferred from the NIC driver with NdisTransferData().
+ \param HeaderBuffer Pointer to the buffer in the NIC driver memory that contains the header of the packet.
+ \param HeaderBufferSize Size in bytes of the header.
+ \param LookAheadBuffer Pointer to the buffer in the NIC driver's memory that contains the incoming packet's
+ data <b>available to NPF</b>. This value does not necessarily coincide with the actual size of the packet,
+ since only a portion can be available at this time. The remaining portion can be obtained with the
+ NdisTransferData() NDIS function.
+ \param LookaheadBufferSize Size in bytes of the lookahead buffer.
+ \param PacketSize Total size of the incoming packet, excluded the header.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ NPF_tap() is called by the underlying NIC for every incoming packet. It is the most important and one of
+ the most complex functions of NPF: it executes the filter, runs the statistical engine (if the instance is in
+ statistical mode), gathers the timestamp, moves the packet in the buffer. NPF_tap() is the only function,
+ along with the filtering ones, that is executed for every incoming packet, therefore it is carefully
+ optimized.
+*/
+NDIS_STATUS
+NPF_tap(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_HANDLE MacReceiveContext,
+ IN PVOID HeaderBuffer,
+ IN UINT HeaderBufferSize,
+ IN PVOID LookAheadBuffer,
+ IN UINT LookaheadBufferSize,
+ IN UINT PacketSize
+ );
+
+/*!
+ \brief Ends the transfer of a packet.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param Packet Pointer to the NDIS_PACKET structure that received the packet data.
+ \param Status Status of the transfer operation.
+ \param BytesTransferred Amount of bytes transferred.
+
+ Callback function associated with the NdisTransferData() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished the transfer of a packet from the NIC driver memory to the NPF circular buffer.
+*/
+VOID
+NPF_TransferDataComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_PACKET Packet,
+ IN NDIS_STATUS Status,
+ IN UINT BytesTransferred
+ );
+
+/*!
+ \brief Callback function that signals the end of a packet reception.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+
+ does nothing in NPF
+*/
+VOID
+NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext);
+
+/*!
+ \brief Handles the IOCTL calls.
+ \param DeviceObject Pointer to the device object utilized by the user.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ Once the packet capture driver is opened it can be configured from user-level applications with IOCTL commands
+ using the DeviceIoControl() system call. NPF_IoControl receives and serves all the IOCTL calls directed to NPF.
+ The following commands are recognized:
+ - #BIOCSETBUFFERSIZE
+ - #BIOCSETF
+ - #BIOCGSTATS
+ - #BIOCSRTIMEOUT
+ - #BIOCSMODE
+ - #BIOCSWRITEREP
+ - #BIOCSMINTOCOPY
+ - #BIOCSETOID
+ - #BIOCQUERYOID
+ - #BIOCSETDUMPFILENAME
+ - #BIOCGEVNAME
+ - #BIOCSENDPACKETSSYNC
+ - #BIOCSENDPACKETSNOSYNC
+*/
+NTSTATUS STDCALL
+NPF_IoControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+
+/*!
+ \brief Ends an OID request.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param pRequest Pointer to the completed OID request.
+ \param Status Status of the operation.
+
+ Callback function associated with the NdisRequest() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished an OID request operation that was previously started by NPF_IoControl().
+*/
+VOID
+NPF_RequestComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_REQUEST pRequest,
+ IN NDIS_STATUS Status
+ );
+
+/*!
+ \brief Writes a raw packet to the network.
+ \param DeviceObject Pointer to the device object on which the user wrote the packet.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function is called by the OS in consequence of user WriteFile() call, with the data of the packet that must
+ be sent on the net. The data is contained in the buffer associated with Irp, NPF_Write takes it and
+ delivers it to the NIC driver via the NdisSend() function. The Nwrites field of the OPEN_INSTANCE structure
+ associated with Irp indicates the number of copies of the packet that will be sent: more than one copy of the
+ packet can be sent for performance reasons.
+*/
+NTSTATUS STDCALL
+NPF_Write(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+
+/*!
+ \brief Writes a buffer of raw packets to the network.
+ \param Irp Pointer to the IRP containing the user request.
+ \param UserBuff Pointer to the buffer containing the packets to send.
+ \param UserBuffSize Size of the buffer with the packets.
+ \return The amount of bytes actually sent. If the return value is smaller than the Size parameter, an
+ error occurred during the send. The error can be caused by an adapter problem or by an
+ inconsistent/bogus user buffer.
+
+ This function is called by the OS in consequence of a BIOCSENDPACKETSNOSYNC or a BIOCSENDPACKETSSYNC IOCTL.
+ The buffer received as input parameter contains an arbitrary number of packets, each of which preceded by a
+ sf_pkthdr structure. NPF_BufferedWrite() scans the buffer and sends every packet via the NdisSend() function.
+ When Sync is set to TRUE, the packets are synchronized with the KeQueryPerformanceCounter() function.
+ This requires a remarkable amount of CPU, but allows to respect the timestamps associated with packets with a precision
+ of some microseconds (depending on the precision of the performance counter of the machine).
+ If Sync is false, the timestamps are ignored and the packets are sent as fat as possible.
+*/
+
+INT NPF_BufferedWrite(IN PIRP Irp,
+ IN PCHAR UserBuff,
+ IN ULONG UserBuffSize,
+ BOOLEAN sync);
+
+/*!
+ \brief Ends a send operation.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param pRequest Pointer to the NDIS PACKET structure used by NPF_Write() to send the packet.
+ \param Status Status of the operation.
+
+ Callback function associated with the NdisSend() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished an OID request operation that was previously started by NPF_Write().
+*/
+VOID
+NPF_SendComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_PACKET pPacket,
+ IN NDIS_STATUS Status
+ );
+
+/*!
+ \brief Ends a reset of the adapter.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param Status Status of the operation.
+
+ Callback function associated with the NdisReset() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished an OID request operation that was previously started by NPF_IoControl(), in an IOCTL_PROTOCOL_RESET
+ command.
+*/
+VOID
+NPF_ResetComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status
+ );
+
+/*!
+ \brief Callback for NDIS StatusHandler. Not used by NPF
+*/
+VOID
+NPF_Status(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN PVOID StatusBuffer,
+ IN UINT StatusBufferSize
+ );
+
+
+/*!
+ \brief Callback for NDIS StatusCompleteHandler. Not used by NPF
+*/
+VOID
+NPF_StatusComplete(IN NDIS_HANDLE ProtocolBindingContext);
+
+/*!
+ \brief Function called by the OS when NPF is unloaded.
+ \param DriverObject The driver object of NPF created by the system.
+
+ This is the last function executed when the driver is unloaded from the system. It frees global resources,
+ delete the devices and deregisters the protocol. The driver can be unloaded by the user stopping the NPF
+ service (from control panel or with a console 'net stop npf').
+*/
+VOID STDCALL
+NPF_Unload(IN PDRIVER_OBJECT DriverObject);
+
+
+/*!
+ \brief Function that serves the user's reads.
+ \param DeviceObject Pointer to the device used by the user.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function is called by the OS in consequence of user ReadFile() call. It moves the data present in the
+ kernel buffer to the user buffer associated with Irp.
+ First of all, NPF_Read checks the amount of data in kernel buffer associated with current NPF instance.
+ - If the instance is in capture mode and the buffer contains more than OPEN_INSTANCE::MinToCopy bytes,
+ NPF_Read moves the data in the user buffer and returns immediatly. In this way, the read performed by the
+ user is not blocking.
+ - If the buffer contains less than MinToCopy bytes, the application's request isn't
+ satisfied immediately, but it's blocked until at least MinToCopy bytes arrive from the net
+ or the timeout on this read expires. The timeout is kept in the OPEN_INSTANCE::TimeOut field.
+ - If the instance is in statistical mode or in dump mode, the application's request is blocked until the
+ timeout kept in OPEN_INSTANCE::TimeOut expires.
+*/
+NTSTATUS STDCALL
+NPF_Read(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+/*!
+ \brief Reads the registry keys associated woth NPF if the driver is manually installed via the control panel.
+
+ Normally not used in recent versions of NPF.
+*/
+NTSTATUS
+NPF_ReadRegistry(
+ IN PWSTR *MacDriverName,
+ IN PWSTR *PacketDriverName,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+/*!
+ \brief Function used by NPF_ReadRegistry() to quesry the registry keys associated woth NPF if the driver
+ is manually installed via the control panel.
+
+ Normally not used in recent versions of NPF.
+*/
+NTSTATUS STDCALL
+NPF_QueryRegistryRoutine(
+ IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext
+ );
+
+/*!
+ \brief Callback for NDIS BindAdapterHandler. Not used by NPF.
+
+ Function called by NDIS when a new adapter is installed on the machine With Plug and Play.
+*/
+VOID NPF_BindAdapter(
+ OUT PNDIS_STATUS Status,
+ IN NDIS_HANDLE BindContext,
+ IN PNDIS_STRING DeviceName,
+ IN PVOID SystemSpecific1,
+ IN PVOID SystemSpecific2
+ );
+
+/*!
+ \brief Callback for NDIS UnbindAdapterHandler.
+ \param Status out variable filled by NPF_UnbindAdapter with the status of the unbind operation.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with current instance.
+ \param UnbindContext Specifies a handle, supplied by NDIS, that NPF can use to complete the opration.
+
+ Function called by NDIS when a new adapter is removed from the machine without shutting it down.
+ NPF_UnbindAdapter closes the adapter calling NdisCloseAdapter() and frees the memory and the structures
+ associated with it. It also releases the waiting user-level app and closes the dump thread if the instance
+ is in dump mode.
+*/
+VOID
+NPF_UnbindAdapter(
+ OUT PNDIS_STATUS Status,
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_HANDLE UnbindContext
+ );
+
+/*!
+ \brief Validates a filtering program arriving from the user-level app.
+ \param f The filter.
+ \param len Its length, in pseudo instructions.
+ \param mem_ex_size The length of the extended memory, used to validate LD/ST to that memory
+ \return true if f is a valid filter program..
+
+ The kernel needs to be able to verify an application's filter code. Otherwise, a bogus program could easily
+ crash the system.
+ This function returns true if f is a valid filter program. The constraints are that each jump be forward and
+ to a valid code. The code must terminate with either an accept or reject.
+*/
+int bpf_validate(struct bpf_insn *f,int len, uint32 mem_ex_size);
+
+/*!
+ \brief The filtering pseudo-machine interpreter.
+ \param pc The filter.
+ \param p Pointer to a memory buffer containing the packet on which the filter will be executed.
+ \param wirelen Original length of the packet.
+ \param buflen Current length of the packet. In some cases (for example when the transfer of the packet to the RAM
+ has not yet finished), bpf_filter can be executed on a portion of the packet.
+ \param mem_ex The extended memory.
+ \param tme The virtualization of the TME co-processor
+ \param time_ref Data structure needed by the TME co-processor to timestamp data
+ \return The portion of the packet to keep, in bytes. 0 means that the packet must be rejected, -1 means that
+ the whole packet must be kept.
+
+ \note this function is not used in normal situations, because the jitter creates a native filtering function
+ that is faster than the interpreter.
+*/
+UINT bpf_filter(register struct bpf_insn *pc,
+ register UCHAR *p,
+ UINT wirelen,
+ register UINT buflen,
+ PMEM_TYPE mem_ex,
+ PTME_CORE tme,
+ struct time_conv *time_ref);
+
+/*!
+ \brief The filtering pseudo-machine interpreter with two buffers. This function is slower than bpf_filter(),
+ but works correctly also if the MAC header and the data of the packet are in two different buffers.
+ \param pc The filter.
+ \param p Pointer to a memory buffer containing the MAC header of the packet.
+ \param pd Pointer to a memory buffer containing the data of the packet.
+ \param wirelen Original length of the packet.
+ \param buflen Current length of the packet. In some cases (for example when the transfer of the packet to the RAM
+ has not yet finished), bpf_filter can be executed on a portion of the packet.
+ \param mem_ex The extended memory.
+ \param tme The virtualization of the TME co-processor
+ \param time_ref Data structure needed by the TME co-processor to timestamp data
+ \return The portion of the packet to keep, in bytes. 0 means that the packet must be rejected, -1 means that
+ the whole packet must be kept.
+
+ This function is used when NDIS passes the packet to NPF_tap() in two buffers instaed than in a single one.
+*/
+UINT bpf_filter_with_2_buffers(register struct bpf_insn *pc,
+ register UCHAR *p,
+ register UCHAR *pd,
+ register int headersize,
+ UINT wirelen,
+ register UINT buflen,
+ PMEM_TYPE mem_ex,
+ PTME_CORE tme,
+ struct time_conv *time_ref);
+
+/*!
+ \brief Creates the file that will receive the packets when the driver is in dump mode.
+ \param Open The NPF instance that opens the file.
+ \param fileName Pointer to a UNICODE string containing the name of the file.
+ \param append Boolean value that specifies if the data must be appended to the file.
+ \return The status of the operation. See ntstatus.h in the DDK.
+*/
+NTSTATUS NPF_OpenDumpFile(POPEN_INSTANCE Open , PUNICODE_STRING fileName, BOOLEAN append);
+
+/*!
+ \brief Starts dump to file.
+ \param Open The NPF instance that opens the file.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function performs two operations. First, it writes the libpcap header at the beginning of the file.
+ Second, it starts the thread that asynchronously dumps the network data to the file.
+*/
+NTSTATUS NPF_StartDump(POPEN_INSTANCE Open);
+
+/*!
+ \brief The dump thread.
+ \param Open The NPF instance that creates the thread.
+
+ This function moves the content of the NPF kernel buffer to file. It runs in the user context, so at lower
+ priority than the TAP.
+*/
+VOID NPF_DumpThread(POPEN_INSTANCE Open);
+
+/*!
+ \brief Saves the content of the packet buffer to the file associated with current instance.
+ \param Open The NPF instance that creates the thread.
+
+ Used by NPF_DumpThread() and NPF_CloseDumpFile().
+*/
+NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open);
+
+/*!
+ \brief Writes a block of packets on the dump file.
+ \param FileObject The file object that will receive the packets.
+ \param Offset The offset in the file where the packets will be put.
+ \param Length The amount of bytes to write.
+ \param Mdl MDL mapping the memory buffer that will be written to disk.
+ \param IoStatusBlock Used by the function to return the status of the operation.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ NPF_WriteDumpFile addresses directly the file system, creating a custom IRP and using it to send a portion
+ of the NPF circular buffer to disk. This function is used by NPF_DumpThread().
+*/
+VOID NPF_WriteDumpFile(PFILE_OBJECT FileObject,
+ PLARGE_INTEGER Offset,
+ ULONG Length,
+ PMDL Mdl,
+ PIO_STATUS_BLOCK IoStatusBlock);
+
+
+
+/*!
+ \brief Closes the dump file associated with an instance of the driver.
+ \param Open The NPF instance that closes the file.
+ \return The status of the operation. See ntstatus.h in the DDK.
+*/
+NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open);
+
+/*!
+ \brief Returns the amount of bytes present in the packet buffer.
+ \param Open The NPF instance that closes the file.
+*/
+UINT GetBuffOccupation(POPEN_INSTANCE Open);
+
+/*!
+ \brief Called by NDIS to notify us of a PNP event. The most significant one for us is power state change.
+
+ \param ProtocolBindingContext Pointer to open context structure. This is NULL for global reconfig
+ events.
+ \param pNetPnPEvent Pointer to the PnP event
+
+ If there is a power state change, the driver is forced to resynchronize the global timer.
+ This hopefully avoids the synchronization issues caused by hibernation or standby.
+ This function is excluded from the NT4 driver, where PnP is not supported
+*/
+#ifdef NDIS50
+NDIS_STATUS NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent);
+#endif
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /*main ifndef/define*/
--- /dev/null
+/*
+ * Copyright (c) 1999, 2000
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef _MSC_VER
+#include <stdarg.h>
+#include <ntddk.h>
+#include <ntiologc.h>
+#include <ndis.h>
+#else
+#include <ddk/ntddk.h>
+#include <net/ndis.h>
+
+#define NdisMoveMappedMemory(Destination,Source,Length) RtlCopyMemory(Destination,Source,Length)
+#define NdisZeroMappedMemory(Destination,Length) RtlZeroMemory(Destination,Length)
+#define NdisReinitializePacket(Packet) \
+{ \
+ (Packet)->Private.Head = (PNDIS_BUFFER)NULL; \
+ (Packet)->Private.ValidCounts = FALSE; \
+}
+
+
+#endif
+
+#include "debug.h"
+#include "packet.h"
+#include "win_bpf.h"
+
+#include "tme.h"
+#include "time_calls.h"
+
+extern struct time_conv G_Start_Time; // from openclos.c
+
+//-------------------------------------------------------------------
+
+UINT GetBuffOccupation(POPEN_INSTANCE Open)
+{
+ UINT Occupation;
+
+ NdisAcquireSpinLock( &Open->BufLock );
+
+ if(Open->Btail >= Open->Bhead) Occupation = Open->Btail-Open->Bhead;
+ else Occupation = Open->BLastByte-Open->Bhead+Open->Btail;
+
+ NdisReleaseSpinLock( &Open->BufLock );
+
+ return Occupation;
+}
+
+//-------------------------------------------------------------------
+
+void PacketMoveMem(PVOID Destination, PVOID Source, ULONG Length, UINT *Bhead)
+{
+ULONG WordLength;
+UINT n,i,NBlocks;
+
+ WordLength=Length>>2;
+ NBlocks=WordLength>>8;
+
+ for(n=0;n<NBlocks;n++){
+ for(i=0;i<256;i++){
+ *((PULONG)Destination)++=*((PULONG)Source)++;
+ }
+ *Bhead+=1024;
+ }
+
+ n=WordLength-(NBlocks<<8);
+ for(i=0;i<n;i++){
+ *((PULONG)Destination)++=*((PULONG)Source)++;
+ }
+ *Bhead+=n<<2;
+
+ n=Length-(WordLength<<2);
+ for(i=0;i<n;i++){
+ *((PUCHAR)Destination)++=*((PUCHAR)Source)++;
+ }
+ *Bhead+=n;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS STDCALL
+NPF_Read(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+{
+ POPEN_INSTANCE Open;
+ PIO_STACK_LOCATION IrpSp;
+ PUCHAR packp;
+ ULONG Input_Buffer_Length;
+ UINT Thead;
+ UINT Ttail;
+ UINT TLastByte;
+ PUCHAR CurrBuff;
+ LARGE_INTEGER CapTime;
+ LARGE_INTEGER TimeFreq;
+ struct bpf_hdr *header;
+ KIRQL Irql;
+ PUCHAR UserPointer;
+ ULONG bytecopy;
+ UINT SizeToCopy;
+ UINT PktLen;
+
+ IF_LOUD(DbgPrint("NPF: Read\n");)
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ Open=IrpSp->FileObject->FsContext;
+
+ if( Open->Bound == FALSE ){
+ // The Network adapter was removed.
+ EXIT_FAILURE(0);
+ }
+
+ if( Open->mode & MODE_DUMP && Open->DumpFileHandle == NULL ){
+ // this instance is in dump mode, but the dump file has still not been opened
+ EXIT_FAILURE(0);
+ }
+
+ //See if the buffer is full enough to be copied
+ if( GetBuffOccupation(Open) <= Open->MinToCopy || Open->mode & MODE_DUMP )
+ {
+ //wait until some packets arrive or the timeout expires
+ if(Open->TimeOut.QuadPart != (LONGLONG)IMMEDIATE)
+ KeWaitForSingleObject(Open->ReadEvent,
+ UserRequest,
+ KernelMode,
+ TRUE,
+ (Open->TimeOut.QuadPart == (LONGLONG)0)? NULL: &(Open->TimeOut));
+
+ KeClearEvent(Open->ReadEvent);
+
+ if(Open->mode & MODE_STAT){ //this capture instance is in statistics mode
+ CurrBuff=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
+
+ //fill the bpf header for this packet
+ header=(struct bpf_hdr*)CurrBuff;
+ GET_TIME(&header->bh_tstamp,&G_Start_Time);
+
+ if(Open->mode & MODE_DUMP){
+ *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+16)=Open->DumpOffset.QuadPart;
+ header->bh_caplen=24;
+ header->bh_datalen=24;
+ Irp->IoStatus.Information = 24 + sizeof(struct bpf_hdr);
+ }
+ else{
+ header->bh_caplen=16;
+ header->bh_datalen=16;
+ header->bh_hdrlen=sizeof(struct bpf_hdr);
+ Irp->IoStatus.Information = 16 + sizeof(struct bpf_hdr);
+ }
+
+ *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr))=Open->Npackets.QuadPart;
+ *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+8)=Open->Nbytes.QuadPart;
+
+ //reset the countetrs
+ NdisAcquireSpinLock( &Open->CountersLock );
+ Open->Npackets.QuadPart=0;
+ Open->Nbytes.QuadPart=0;
+ NdisReleaseSpinLock( &Open->CountersLock );
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return STATUS_SUCCESS;
+ }
+
+ if(Open->mode==MODE_MON) //this capture instance is in monitor mode
+ {
+ PTME_DATA data;
+ ULONG cnt;
+ ULONG block_size;
+ PUCHAR tmp;
+
+ UserPointer=MmGetSystemAddressForMdl(Irp->MdlAddress);
+
+ if ((!IS_VALIDATED(Open->tme.validated_blocks,Open->tme.active_read))||(IrpSp->Parameters.Read.Length<sizeof(struct bpf_hdr)))
+ {
+ EXIT_FAILURE(0);
+ }
+
+ header=(struct bpf_hdr*)UserPointer;
+
+ GET_TIME(&header->bh_tstamp,&G_Start_Time);
+
+
+ header->bh_hdrlen=sizeof(struct bpf_hdr);
+
+
+ //moves user memory pointer
+ UserPointer+=sizeof(struct bpf_hdr);
+
+ //calculus of data to be copied
+ //if the user buffer is smaller than data to be copied,
+ //only some data will be copied
+ data=&Open->tme.block_data[Open->tme.active_read];
+
+ if (data->last_read.tv_sec!=0)
+ data->last_read=header->bh_tstamp;
+
+
+ bytecopy=data->block_size*data->filled_blocks;
+
+ if ((IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))<bytecopy)
+ bytecopy=(IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))/ data->block_size;
+ else
+ bytecopy=data->filled_blocks;
+
+ tmp=data->shared_memory_base_address;
+ block_size=data->block_size;
+
+ for (cnt=0;cnt<bytecopy;cnt++)
+ {
+ NdisAcquireSpinLock(&Open->machine_lock);
+ RtlCopyMemory(UserPointer,tmp,block_size);
+ NdisReleaseSpinLock(&Open->machine_lock);
+ tmp+=block_size;
+ UserPointer+=block_size;
+ }
+
+ bytecopy*=block_size;
+
+ header->bh_caplen=bytecopy;
+ header->bh_datalen=header->bh_caplen;
+
+ EXIT_SUCCESS(bytecopy+sizeof(struct bpf_hdr));
+ }
+
+ if (Open->Bhead == Open->Btail || Open->mode & MODE_DUMP)
+ // The timeout has expired, but the buffer is still empty (or the packets must be written to file).
+ // We must awake the application, returning an empty buffer.
+ {
+ EXIT_SUCCESS(0);
+ }
+
+ }
+
+ //
+ // The buffer if full enough to be copied,
+ //
+ NdisAcquireSpinLock( &Open->BufLock );
+
+ Thead = Open->Bhead;
+ Ttail = Open->Btail;
+ TLastByte = Open->BLastByte;
+
+ //get the address of the buffer
+ CurrBuff=Open->Buffer;
+
+ NdisReleaseSpinLock( &Open->BufLock );
+
+ Input_Buffer_Length=IrpSp->Parameters.Read.Length;
+ packp=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
+
+
+ //
+ //fill the application buffer
+ //
+ if(Ttail > Thead){ //first of all see if it we can copy all the buffer in one time
+ if((Ttail-Thead)<Input_Buffer_Length){
+ KeResetEvent(Open->ReadEvent);
+
+ PacketMoveMem(packp,CurrBuff+Thead,Ttail-Thead,&(Open->Bhead));
+ EXIT_SUCCESS(Ttail-Thead);
+ }
+ }
+ else if((TLastByte - Thead) < Input_Buffer_Length){
+ PacketMoveMem(packp, CurrBuff+Thead, TLastByte - Thead, &(Open->Bhead));
+
+ NdisAcquireSpinLock( &Open->BufLock );
+
+ Open->BLastByte = Open->Btail;
+ Open->Bhead = 0;
+
+ NdisReleaseSpinLock( &Open->BufLock );
+
+ EXIT_SUCCESS(TLastByte-Thead);
+ }
+
+ //the buffer must be scannned to determine the number of bytes to copy
+ SizeToCopy = 0;
+ while(TRUE){
+ if(Thead + SizeToCopy == Ttail)
+ break;
+
+ if(Thead + SizeToCopy == TLastByte && TLastByte != Ttail){
+
+ PacketMoveMem(packp, CurrBuff+Thead, SizeToCopy, &(Open->Bhead));
+ // Reset the buffer
+ NdisAcquireSpinLock( &Open->BufLock );
+ (INT)Open->BLastByte = -1;
+ Open->Bhead = 0;
+ NdisReleaseSpinLock( &Open->BufLock );
+
+ EXIT_SUCCESS(SizeToCopy);
+ }
+
+ // Get the size of the next packet in the buffer
+ PktLen = ((struct bpf_hdr*)(CurrBuff + Thead + SizeToCopy))->bh_caplen + sizeof(struct bpf_hdr);
+
+ // The length is aligned to 32-bit boundary
+ PktLen = Packet_WORDALIGN(PktLen);
+
+ if(SizeToCopy + PktLen > Input_Buffer_Length)
+ break;
+
+ SizeToCopy += PktLen;
+ }
+
+ PacketMoveMem(packp, CurrBuff+Thead, SizeToCopy, &(Open->Bhead));
+ EXIT_SUCCESS(SizeToCopy);
+
+}
+
+//-------------------------------------------------------------------
+
+NDIS_STATUS NPF_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE MacReceiveContext,
+ IN PVOID HeaderBuffer,IN UINT HeaderBufferSize,IN PVOID LookAheadBuffer,
+ IN UINT LookaheadBufferSize,IN UINT PacketSize)
+{
+ POPEN_INSTANCE Open;
+ PNDIS_PACKET pPacketb;
+ ULONG SizeToTransfer;
+ NDIS_STATUS Status;
+ UINT BytesTransfered;
+ ULONG BufferLength;
+ PMDL pMdl;
+ LARGE_INTEGER CapTime;
+ LARGE_INTEGER TimeFreq;
+ struct bpf_hdr *header;
+ PUCHAR CurrBuff;
+ UINT Thead;
+ UINT Ttail;
+ UINT TLastByte;
+ UINT fres;
+ UINT maxbufspace;
+ USHORT NPFHdrSize;
+ UINT BufOccupation;
+ BOOLEAN ResetBuff = FALSE;
+
+ IF_VERY_LOUD(DbgPrint("NPF: tap\n");)
+ IF_VERY_LOUD(DbgPrint("HeaderBufferSize=%d, LookAheadBuffer=%d, LookaheadBufferSize=%d, PacketSize=%d\n",
+ HeaderBufferSize,
+ LookAheadBuffer,
+ LookaheadBufferSize,
+ PacketSize);)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+ Open->Received++; // Number of packets received by filter ++
+
+ BufOccupation = GetBuffOccupation(Open); // Get the full buffer space
+
+ if(((Open->mode&MODE_CAPT)||(Open->mode&MODE_DUMP)) && Open->BufSize - BufOccupation < PacketSize+HeaderBufferSize+sizeof(struct bpf_hdr)){
+ // Heuristic that drops the packet also if it possibly fits in the buffer.
+ // It allows to avoid filtering in critical situations when CPU is very important.
+ Open->Dropped++;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ NdisAcquireSpinLock(&Open->machine_lock);
+
+ //
+ //Check if the lookahead buffer follows the mac header.
+ //If the data follow the header (i.e. there is only a buffer) a normal bpf_filter() is
+ //executed on the packet.
+ //Otherwise if there are 2 separate buffers (this could be the case of LAN emulation or
+ //things like this) bpf_filter_with_2_buffers() is executed.
+ //
+ if((UINT)LookAheadBuffer-(UINT)HeaderBuffer != HeaderBufferSize)
+ fres=bpf_filter_with_2_buffers((struct bpf_insn*)(Open->bpfprogram),
+ HeaderBuffer,
+ LookAheadBuffer,
+ HeaderBufferSize,
+ PacketSize+HeaderBufferSize,
+ LookaheadBufferSize+HeaderBufferSize,
+ &Open->mem_ex,
+ &Open->tme,
+ &G_Start_Time);
+
+
+ else
+ if(Open->Filter != NULL)
+ {
+ if (Open->bpfprogram != NULL)
+ {
+ fres=Open->Filter->Function(HeaderBuffer,
+ PacketSize+HeaderBufferSize,
+ LookaheadBufferSize+HeaderBufferSize);
+
+ // Restore the stack.
+ // I ignore the reason, but this instruction is needed only at kernel level
+#ifndef __GNUC__
+ _asm add esp,12
+#else
+ asm("add $0x12,%esp;");
+#endif
+ }
+ else
+ fres = -1;
+ }
+ else
+ fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram),
+ HeaderBuffer,
+ PacketSize+HeaderBufferSize,
+ LookaheadBufferSize+HeaderBufferSize,
+ &Open->mem_ex,
+ &Open->tme,
+ &G_Start_Time);
+
+ NdisReleaseSpinLock(&Open->machine_lock);
+
+ if(Open->mode==MODE_MON)
+ // we are in monitor mode
+ {
+ if (fres==1)
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ }
+
+ if(fres==0)
+ // Packet not accepted by the filter, ignore it.
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ //if the filter returns -1 the whole packet must be accepted
+ if(fres==-1 || fres > PacketSize+HeaderBufferSize)fres=PacketSize+HeaderBufferSize;
+
+ if(Open->mode & MODE_STAT){
+ // we are in statistics mode
+ NdisAcquireSpinLock( &Open->CountersLock );
+
+ Open->Npackets.QuadPart++;
+
+ if(PacketSize+HeaderBufferSize<60)
+ Open->Nbytes.QuadPart+=60;
+ else
+ Open->Nbytes.QuadPart+=PacketSize+HeaderBufferSize;
+ // add preamble+SFD+FCS to the packet
+ // these values must be considered because are not part of the packet received from NDIS
+ Open->Nbytes.QuadPart+=12;
+
+ NdisReleaseSpinLock( &Open->CountersLock );
+
+ if(!(Open->mode & MODE_DUMP)){
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+ }
+
+ if(Open->BufSize==0)return NDIS_STATUS_NOT_ACCEPTED;
+
+ if(Open->mode & MODE_DUMP && Open->MaxDumpPacks && (UINT)Open->Accepted > Open->MaxDumpPacks){
+ // Reached the max number of packets to save in the dump file. Discard the packet and stop the dump thread.
+ Open->DumpLimitReached = TRUE; // This stops the thread
+ // Awake the dump thread
+ NdisSetEvent(&Open->DumpEvent);
+
+ // Awake the application
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ // Calculate the correct size for the header associated with the packet
+ NPFHdrSize=(Open->mode==MODE_CAPT)? sizeof(struct bpf_hdr): sizeof(struct sf_pkthdr);
+
+ NdisAcquireSpinLock( &Open->BufLock );
+
+ Thead=Open->Bhead;
+ Ttail=Open->Btail;
+ TLastByte = Open->BLastByte;
+
+ NdisReleaseSpinLock( &Open->BufLock );
+
+ maxbufspace=Packet_WORDALIGN(fres+NPFHdrSize);
+
+ if(Ttail+maxbufspace >= Open->BufSize){
+ if(Thead <= maxbufspace)
+ {
+ Open->Dropped++;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+ else{
+ Ttail=0;
+ ResetBuff = TRUE;
+ }
+ }
+
+ if (Thead > Ttail && (Thead-Ttail) <= maxbufspace)
+ {
+ Open->Dropped++;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ CurrBuff=Open->Buffer+Ttail;
+
+ if(LookaheadBufferSize != PacketSize || (UINT)LookAheadBuffer-(UINT)HeaderBuffer != HeaderBufferSize)
+ {
+ // Allocate an MDL to map the portion of the buffer following the header
+ pMdl=IoAllocateMdl(CurrBuff+HeaderBufferSize+LookaheadBufferSize+NPFHdrSize,
+ maxbufspace,
+ FALSE,
+ FALSE,
+ NULL);
+
+ if (pMdl == NULL)
+ {
+ // Unable to map the memory: packet lost
+ IF_LOUD(DbgPrint("NPF: Read-Failed to allocate Mdl\n");)
+ Open->Dropped++;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+ MmBuildMdlForNonPagedPool(pMdl);
+
+ //allocate the packet from NDIS
+ NdisAllocatePacket(&Status, &pPacketb, Open->PacketPool);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ IF_LOUD(DbgPrint("NPF: Tap - No free packets\n");)
+ IoFreeMdl(pMdl);
+ Open->Dropped++;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+ //link the buffer to the packet
+ NdisChainBufferAtFront(pPacketb,pMdl);
+
+ BufferLength=fres-HeaderBufferSize;
+ //Find out how much to transfer
+ SizeToTransfer = (PacketSize < BufferLength) ? PacketSize : BufferLength;
+
+ //copy the ethernet header into buffer
+ NdisMoveMappedMemory((CurrBuff)+NPFHdrSize,HeaderBuffer,HeaderBufferSize);
+
+ //Copy the look ahead buffer
+ if(LookaheadBufferSize)
+ {
+ NdisMoveMappedMemory((CurrBuff) + NPFHdrSize + HeaderBufferSize,
+ LookAheadBuffer,
+ (SizeToTransfer < LookaheadBufferSize)? SizeToTransfer : LookaheadBufferSize );
+
+ SizeToTransfer = (SizeToTransfer > LookaheadBufferSize)?
+ SizeToTransfer - LookaheadBufferSize : 0;
+ }
+
+ Open->TransferMdl=pMdl;
+
+ if(SizeToTransfer)
+ {
+ //Call the Mac to transfer the packet
+ NdisTransferData(&Status,
+ Open->AdapterHandle,
+ MacReceiveContext,
+ LookaheadBufferSize,
+ SizeToTransfer,
+ pPacketb,
+ &BytesTransfered);
+ }
+ else{
+ BytesTransfered = 0;
+ }
+
+ }
+ else
+ {
+ // The whole packet is in the lookahead buffer, we can avoid the call to NdisTransferData.
+ // This allows us to avoid the allocation of the MDL and the NDIS packet as well
+ RtlCopyMemory((CurrBuff) + NPFHdrSize,
+ HeaderBuffer,
+ HeaderBufferSize + LookaheadBufferSize);
+
+ BytesTransfered = 0;
+
+ Open->TransferMdl = NULL;
+ Status = NDIS_STATUS_SUCCESS;
+ }
+
+ if (Status != NDIS_STATUS_FAILURE)
+ {
+
+ Open->Accepted++; // Increase the accepted packets counter
+
+ if( fres > (BytesTransfered+HeaderBufferSize+LookaheadBufferSize) )
+ fres = BytesTransfered+HeaderBufferSize+LookaheadBufferSize;
+
+ //
+ // Build the header
+ //
+ header=(struct bpf_hdr*)CurrBuff;
+ GET_TIME(&header->bh_tstamp,&G_Start_Time);
+ header->bh_caplen=fres;
+ header->bh_datalen=PacketSize+HeaderBufferSize;
+ if(Open->mode==MODE_CAPT){
+ header->bh_hdrlen=NPFHdrSize;
+ // Don't align if the packet goes to disk
+ Ttail+=Packet_WORDALIGN(fres + NPFHdrSize);
+ }
+ else
+ Ttail+=fres+NPFHdrSize;
+
+ //update the buffer
+ NdisAcquireSpinLock( &Open->BufLock );
+
+ if(ResetBuff){
+ Open->BLastByte = Open->Btail;
+ }
+ Open->Btail=Ttail;
+
+ NdisReleaseSpinLock( &Open->BufLock );
+ }
+
+ if (Status != NDIS_STATUS_PENDING){
+
+ if( Open->TransferMdl != NULL)
+ // Complete the request and free the buffers
+ NPF_TransferDataComplete(Open,pPacketb,Status,fres);
+ else{
+ // Unfreeze the consumer
+ if(GetBuffOccupation(Open)>Open->MinToCopy){
+ if(Open->mode & MODE_DUMP){
+ NdisSetEvent(&Open->DumpEvent);
+ }
+ else
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+ }
+
+ }
+ }
+
+ return NDIS_STATUS_SUCCESS;
+
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_TransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET pPacket,
+ IN NDIS_STATUS Status,IN UINT BytesTransfered)
+{
+ POPEN_INSTANCE Open;
+
+ IF_LOUD(DbgPrint("NPF: TransferDataComplete\n");)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+ IoFreeMdl(Open->TransferMdl);
+ //recylcle the packet
+ NdisReinitializePacket(pPacket);
+ //Put the packet on the free queue
+ NdisFreePacket(pPacket);
+ // Unfreeze the consumer
+ if(GetBuffOccupation(Open)>Open->MinToCopy){
+ if(Open->mode & MODE_DUMP){
+ NdisSetEvent(&Open->DumpEvent);
+ }
+ else
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+ }
+ return;
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext)
+{
+ IF_VERY_LOUD(DbgPrint("NPF: NPF_ReceiveComplete\n");)
+ return;
+}
--- /dev/null
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by NPF.RC
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "tcp_session.h"
+#endif
+
+#ifdef __FreeBSD
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/tme/tcp_session.h>
+#else
+#include <tme/tme.h>
+#include <tme/tcp_session.h>
+#endif
+
+#endif
+
+uint32 tcp_session(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data)
+
+{
+
+ uint32 next_status;
+ uint32 direction=ULONG_AT(mem_data,12);
+ uint8 flags=mem_ex->buffer[25];
+ tcp_data *session=(tcp_data*)(block+data->key_len*4);
+
+ session->last_timestamp=session->timestamp_block;
+ session->timestamp_block.tv_sec=0x7fffffff;
+
+ if (direction==session->direction)
+ {
+ session->pkts_cln_to_srv++;
+ session->bytes_cln_to_srv+=pkt_size;
+ }
+ else
+ {
+ session->pkts_srv_to_cln++;
+ session->bytes_srv_to_cln+=pkt_size;
+ }
+ /* we use only thes four flags, we don't need PSH or URG */
+ flags&=(ACK|FIN|SYN|RST);
+
+ switch (session->status)
+ {
+ case ERROR_TCP:
+ next_status=ERROR_TCP;
+ break;
+
+ case UNKNOWN:
+ if (flags==SYN)
+ {
+ if (SW_ULONG_AT(mem_ex->buffer,20)!=0)
+ {
+
+ next_status=ERROR_TCP;
+ break;
+ }
+ next_status=SYN_RCV;
+ session->syn_timestamp=session->last_timestamp;
+
+ session->direction=direction;
+ session->seq_n_0_cln=SW_ULONG_AT(mem_ex->buffer,16);
+ }
+ else
+ next_status=UNKNOWN;
+ break;
+
+ case SYN_RCV:
+ if ((flags&RST)&&(direction!=session->direction))
+ {
+ next_status=CLOSED_RST;
+ break;
+ }
+ if ((flags==SYN)&&(direction==session->direction))
+ { /* two syns... */
+ next_status=SYN_RCV;
+ session->seq_n_0_cln=SW_ULONG_AT(mem_ex->buffer,16);
+ break;
+ }
+
+ if ((flags==(SYN|ACK))&&(direction!=session->direction))
+ {
+ if (SW_ULONG_AT(mem_ex->buffer,20)!=session->seq_n_0_cln+1)
+ {
+ next_status=ERROR_TCP;
+ break;
+ }
+ next_status=SYN_ACK_RCV;
+
+ session->syn_ack_timestamp=session->last_timestamp;
+
+ session->seq_n_0_srv=SW_ULONG_AT(mem_ex->buffer,16);
+ session->ack_cln=session->seq_n_0_cln+1;
+ }
+ else
+ {
+ next_status=ERROR_TCP;
+ }
+ break;
+
+ case SYN_ACK_RCV:
+ if ((flags&ACK)&&(flags&RST)&&(direction==session->direction))
+ {
+ next_status=CLOSED_RST;
+ session->ack_srv=SW_ULONG_AT(mem_ex->buffer,20);
+ break;
+ }
+
+ if ((flags==ACK)&&(!(flags&(SYN|FIN|RST)))&&(direction==session->direction))
+ {
+ if (SW_ULONG_AT(mem_ex->buffer,20)!=session->seq_n_0_srv+1)
+ {
+ next_status=ERROR_TCP;
+ break;
+ }
+ next_status=ESTABLISHED;
+ session->ack_srv=session->seq_n_0_srv+1;
+ break;
+ }
+ if ((flags&ACK)&&(flags&SYN)&&(direction!=session->direction))
+ {
+ next_status=SYN_ACK_RCV;
+ break;
+ }
+
+ next_status=ERROR_TCP;
+ break;
+
+ case ESTABLISHED:
+ if (flags&SYN)
+ {
+ if ((flags&ACK)&&
+ (direction!=session->direction)&&
+ ((session->ack_cln-SW_ULONG_AT(mem_ex->buffer,20))<MAX_WINDOW)
+ )
+ { /* SYN_ACK duplicato */
+ next_status=ESTABLISHED;
+ break;
+ }
+
+ if ((!(flags&ACK))&&
+ (direction==session->direction)&&
+ (SW_ULONG_AT(mem_ex->buffer,16)==session->seq_n_0_cln)&&
+ (ULONG_AT(mem_ex->buffer,20)==0)
+ )
+ { /* syn duplicato */
+ next_status=ESTABLISHED;
+ break;
+ }
+
+ next_status=ERROR_TCP;
+ break;
+ }
+ if (flags&ACK)
+ if (direction==session->direction)
+ {
+ uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
+ if (new_ack-session->ack_srv<MAX_WINDOW)
+ session->ack_srv=new_ack;
+ }
+ else
+ {
+ uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
+ if (new_ack-session->ack_cln<MAX_WINDOW)
+ session->ack_cln=new_ack;
+ }
+ if (flags&RST)
+ {
+ next_status=CLOSED_RST;
+ break;
+ }
+ if (flags&FIN)
+ if (direction==session->direction)
+ { /* an hack to make all things work */
+ session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16);
+ next_status=FIN_CLN_RCV;
+ break;
+ }
+ else
+ {
+ session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16);
+ next_status=FIN_SRV_RCV;
+ break;
+ }
+ next_status=ESTABLISHED;
+ break;
+
+ case CLOSED_RST:
+ next_status=CLOSED_RST;
+ break;
+
+ case FIN_SRV_RCV:
+ if (flags&SYN)
+ {
+ next_status=ERROR_TCP;
+ break;
+ }
+
+ next_status=FIN_SRV_RCV;
+
+ if (flags&ACK)
+ {
+ uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
+ if (direction!=session->direction)
+ if ((new_ack-session->ack_cln)<MAX_WINDOW)
+ session->ack_cln=new_ack;
+ }
+
+ if (flags&RST)
+ next_status=CLOSED_RST;
+ else
+ if ((flags&FIN)&&(direction==session->direction))
+ {
+ session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16);
+ next_status=CLOSED_FIN;
+ }
+
+ break;
+
+ case FIN_CLN_RCV:
+ if (flags&SYN)
+ {
+ next_status=ERROR_TCP;
+ break;
+ }
+
+ next_status=FIN_CLN_RCV;
+
+ if (flags&ACK)
+ {
+ uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
+ if (direction==session->direction)
+ if (new_ack-session->ack_srv<MAX_WINDOW)
+ session->ack_srv=new_ack;
+ }
+
+ if (flags&RST)
+ next_status=CLOSED_RST;
+ else
+ if ((flags&FIN)&&(direction!=session->direction))
+ {
+ session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16);
+ next_status=CLOSED_FIN;
+ }
+
+ break;
+
+ case CLOSED_FIN:
+ next_status=CLOSED_FIN;
+ break;
+ default:
+ next_status=ERROR_TCP;
+
+ }
+
+ session->status=next_status;
+
+ if ((next_status==CLOSED_FIN)||(next_status==UNKNOWN)||(next_status==CLOSED_RST)||(next_status==ERROR_TCP))
+ session->timestamp_block=session->last_timestamp;
+
+ return TME_SUCCESS;
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __tcp_session
+#define __tcp_session
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#endif
+
+#endif
+
+#define UNKNOWN 0
+#define SYN_RCV 1
+#define SYN_ACK_RCV 2
+#define ESTABLISHED 3
+#define CLOSED_RST 4
+#define FIN_CLN_RCV 5
+#define FIN_SRV_RCV 6
+#define CLOSED_FIN 7
+#define ERROR_TCP 8
+#define FIRST_IS_CLN 0
+#define FIRST_IS_SRV 0xffffffff
+#define FIN_CLN 1
+#define FIN_SRV 2
+
+#define MAX_WINDOW 65536
+
+typedef struct __tcp_data
+{
+ struct timeval timestamp_block; /*DO NOT MOVE THIS VALUE*/
+ struct timeval syn_timestamp;
+ struct timeval last_timestamp;
+ struct timeval syn_ack_timestamp;
+ uint32 direction;
+ uint32 seq_n_0_srv;
+ uint32 seq_n_0_cln;
+ uint32 ack_srv; /* acknowledge of (data sent by server) */
+ uint32 ack_cln; /* acknowledge of (data sent by client) */
+ uint32 status;
+ uint32 pkts_cln_to_srv;
+ uint32 pkts_srv_to_cln;
+ uint32 bytes_srv_to_cln;
+ uint32 bytes_cln_to_srv;
+ uint32 close_state;
+}
+ tcp_data;
+
+#define FIN 1
+#define SYN 2
+#define RST 4
+#define PSH 8
+#define ACK 16
+#define URG 32
+
+#define TCP_SESSION 0x00000800
+uint32 tcp_session(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
+
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "tme.h"
+#include "win_bpf.h"
+#include "time_calls.h"
+
+
+void TIME_DESYNCHRONIZE(struct time_conv *data)
+{
+ data->reference = 0;
+ data->start.tv_sec = 0;
+ data->start.tv_usec = 0;
+}
+
+#ifdef KQPC_TS
+
+/* KeQueryPerformanceCounter TimeStamps */
+
+VOID TIME_SYNCHRONIZE(struct time_conv *data)
+{
+ struct timeval tmp;
+ LARGE_INTEGER SystemTime;
+ LARGE_INTEGER i;
+ ULONG tmp2;
+ LARGE_INTEGER TimeFreq,PTime;
+
+ if (data->reference!=0)
+ return;
+
+ // get the absolute value of the system boot time.
+ PTime=KeQueryPerformanceCounter(&TimeFreq);
+ KeQuerySystemTime(&SystemTime);
+#ifndef __GNUC__
+ tmp.tv_sec=(LONG)(SystemTime.QuadPart/10000000-11644473600);
+ tmp.tv_usec=(LONG)((SystemTime.QuadPart%10000000)/10);
+ tmp.tv_sec-=(ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
+ tmp.tv_usec-=(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+#else
+ // TODO FIXME:
+#endif
+ if (tmp.tv_usec<0) {
+ tmp.tv_sec--;
+ tmp.tv_usec+=1000000;
+ }
+ data->start=tmp;
+ data->reference=1;
+}
+
+void FORCE_TIME(struct timeval *src, struct time_conv *dest)
+{
+ dest->start=*src;
+}
+
+void GET_TIME(struct timeval *dst, struct time_conv *data)
+{
+ LARGE_INTEGER PTime, TimeFreq;
+ LONG tmp;
+
+ PTime=KeQueryPerformanceCounter(&TimeFreq);
+#ifndef __GNUC__
+ tmp=(LONG)(PTime.QuadPart/TimeFreq.QuadPart);
+ dst->tv_sec=data->start.tv_sec+tmp;
+ dst->tv_usec=data->start.tv_usec+(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+#else
+ // TODO FIXME:
+#endif
+ if (dst->tv_usec>=1000000) {
+ dst->tv_sec++;
+ dst->tv_usec-=1000000;
+ }
+}
+
+#else /*KQPC_TS*/
+
+/*RDTSC timestamps*/
+
+/* callers must be at IRQL=PASSIVE_LEVEL */
+VOID TIME_SYNCHRONIZE(struct time_conv *data)
+{
+ struct timeval tmp;
+ LARGE_INTEGER system_time;
+ ULONGLONG curr_ticks;
+ KIRQL old;
+ LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq;
+ ULONGLONG start_ticks,stop_ticks;
+ ULONGLONG delta,delta2;
+ KEVENT event;
+ LARGE_INTEGER i;
+ ULONGLONG reference;
+
+ if (data->reference!=0)
+ return;
+
+ KeInitializeEvent(&event,NotificationEvent,FALSE);
+ i.QuadPart=-3500000;
+ KeRaiseIrql(HIGH_LEVEL,&old);
+ start_kqpc=KeQueryPerformanceCounter(&start_freq);
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, start_ticks
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+#else
+ asm("push %%eax;"
+ "push %%edx;"
+ "push %%ecx;"
+ "rdtsc;"
+ "lea %0,%%ecx;"
+ "mov %%edx,(%%ecx+4);"
+ "mov %%eax,(%%ecx);"
+ "pop %%ecx;"
+ "pop %%edx;"
+ "pop %%eax;"
+ :"=c"(start_ticks): );
+#endif
+ KeLowerIrql(old);
+ KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
+ KeRaiseIrql(HIGH_LEVEL,&old);
+ stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, stop_ticks
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+#else
+ asm("push %%eax;"
+ "push %%edx;"
+ "push %%ecx;"
+ "rdtsc;"
+ "lea %0,%%ecx;"
+ "mov %%edx,(%%ecx+4);"
+ "mov %%eax,(%%ecx);"
+ "pop %%ecx;"
+ "pop %%edx;"
+ "pop %%eax;"
+ :"=c"(stop_ticks): );
+#endif
+ KeLowerIrql(old);
+ delta=stop_ticks-start_ticks;
+ delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;
+ if (delta>10000000000) {
+ delta/=16;
+ delta2/=16;
+ }
+ reference=delta*(start_freq.QuadPart)/delta2;
+ data->reference=reference/1000;
+ if (reference%1000>500)
+ data->reference++;
+ data->reference*=1000;
+ reference=data->reference;
+ KeQuerySystemTime(&system_time);
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, curr_ticks
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+#else
+ asm("push %%eax;"
+ "push %%edx;"
+ "push %%ecx;"
+ "rdtsc;"
+ "lea %0,%%ecx;"
+ "mov %%edx,(%%ecx+4);"
+ "mov %%eax,(%%ecx);"
+ "pop %%ecx;"
+ "pop %%edx;"
+ "pop %%eax;"
+ :"=c"(curr_ticks): );
+#endif
+ tmp.tv_sec=-(LONG)(curr_ticks/reference);
+ tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);
+ system_time.QuadPart-=116444736000000000;
+ tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);
+ tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);
+ if (tmp.tv_usec<0) {
+ tmp.tv_sec--;
+ tmp.tv_usec+=1000000;
+ }
+ data->start=tmp;
+ IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)
+}
+
+void FORCE_TIME(struct timeval *src, struct time_conv *dest)
+{
+ dest->start=*src;
+}
+
+void GET_TIME(struct timeval *dst, struct time_conv *data)
+{
+ ULONGLONG tmp;
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, tmp
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+#else
+ asm("push %%eax;"
+ "push %%edx;"
+ "push %%ecx;"
+ "rdtsc;"
+ "lea %0,%%ecx;"
+ "mov %%edx,(%%ecx+4);"
+ "mov %%eax,(%%ecx);"
+ "pop %%ecx;"
+ "pop %%edx;"
+ "pop %%eax;"
+ :"=c"(tmp): );
+#endif
+ if (data->reference==0) {
+ return;
+ }
+ dst->tv_sec=(LONG)(tmp/data->reference);
+ dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);
+ dst->tv_sec+=data->start.tv_sec;
+ dst->tv_usec+=data->start.tv_usec;
+ if (dst->tv_usec>=1000000) {
+ dst->tv_sec++;
+ dst->tv_usec-=1000000;
+ }
+}
+
+#endif /*KQPC_TS*/
--- /dev/null
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef _time_calls
+#define _time_calls
+
+#ifdef WIN_NT_DRIVER
+
+#include "debug.h"
+
+/*!
+ \brief A microsecond precise timestamp.
+
+ included in the sf_pkthdr or the bpf_hdr that NPF associates with every packet.
+*/
+
+struct timeval {
+ long tv_sec; ///< seconds
+ long tv_usec; ///< microseconds
+};
+
+#endif /*WIN_NT_DRIVER*/
+
+struct time_conv {
+ ULONGLONG reference;
+ struct timeval start;
+};
+
+#ifdef __GNUC__
+
+void TIME_DESYNCHRONIZE(struct time_conv *data);
+VOID TIME_SYNCHRONIZE(struct time_conv *data);
+void FORCE_TIME(struct timeval *src, struct time_conv *dest);
+void GET_TIME(struct timeval *dst, struct time_conv *data);
+
+#else /* __GNUC__ */
+
+#ifdef WIN_NT_DRIVER
+
+__inline void TIME_DESYNCHRONIZE(struct time_conv *data)
+{
+ data->reference = 0;
+ data->start.tv_sec = 0;
+ data->start.tv_usec = 0;
+}
+
+#ifdef KQPC_TS
+
+/* KeQueryPerformanceCounter TimeStamps */
+
+__inline VOID TIME_SYNCHRONIZE(struct time_conv *data)
+{
+ struct timeval tmp;
+ LARGE_INTEGER SystemTime;
+ LARGE_INTEGER i;
+ ULONG tmp2;
+ LARGE_INTEGER TimeFreq,PTime;
+
+ if (data->reference!=0)
+ return;
+
+ // get the absolute value of the system boot time.
+ PTime=KeQueryPerformanceCounter(&TimeFreq);
+ KeQuerySystemTime(&SystemTime);
+ tmp.tv_sec=(LONG)(SystemTime.QuadPart/10000000-11644473600);
+ tmp.tv_usec=(LONG)((SystemTime.QuadPart%10000000)/10);
+ tmp.tv_sec-=(ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
+ tmp.tv_usec-=(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+ if (tmp.tv_usec<0) {
+ tmp.tv_sec--;
+ tmp.tv_usec+=1000000;
+ }
+ data->start=tmp;
+ data->reference=1;
+}
+
+__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
+{
+ LARGE_INTEGER PTime, TimeFreq;
+ LONG tmp;
+
+ PTime=KeQueryPerformanceCounter(&TimeFreq);
+ tmp=(LONG)(PTime.QuadPart/TimeFreq.QuadPart);
+ dst->tv_sec=data->start.tv_sec+tmp;
+ dst->tv_usec=data->start.tv_usec+(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+ if (dst->tv_usec>=1000000) {
+ dst->tv_sec++;
+ dst->tv_usec-=1000000;
+ }
+}
+
+__inline void FORCE_TIME(struct timeval *src, struct time_conv *dest)
+{
+ dest->start=*src;
+}
+
+#else
+
+/*RDTSC timestamps*/
+
+/* callers must be at IRQL=PASSIVE_LEVEL */
+__inline VOID TIME_SYNCHRONIZE(struct time_conv *data)
+{
+ struct timeval tmp;
+ LARGE_INTEGER system_time;
+ ULONGLONG curr_ticks;
+ KIRQL old;
+ LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq;
+ ULONGLONG start_ticks,stop_ticks;
+ ULONGLONG delta,delta2;
+ KEVENT event;
+ LARGE_INTEGER i;
+ ULONGLONG reference;
+
+ if (data->reference!=0)
+ return;
+
+ KeInitializeEvent(&event,NotificationEvent,FALSE);
+ i.QuadPart=-3500000;
+ KeRaiseIrql(HIGH_LEVEL,&old);
+ start_kqpc=KeQueryPerformanceCounter(&start_freq);
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, start_ticks
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+#else
+#endif
+ KeLowerIrql(old);
+ KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
+ KeRaiseIrql(HIGH_LEVEL,&old);
+ stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, stop_ticks
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+#else
+#endif
+ KeLowerIrql(old);
+ delta=stop_ticks-start_ticks;
+ delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;
+ if (delta>10000000000) {
+ delta/=16;
+ delta2/=16;
+ }
+ reference=delta*(start_freq.QuadPart)/delta2;
+ data->reference=reference/1000;
+ if (reference%1000>500)
+ data->reference++;
+ data->reference*=1000;
+ reference=data->reference;
+ KeQuerySystemTime(&system_time);
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, curr_ticks
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+#else
+#endif
+ tmp.tv_sec=-(LONG)(curr_ticks/reference);
+ tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);
+ system_time.QuadPart-=116444736000000000;
+ tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);
+ tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);
+ if (tmp.tv_usec<0) {
+ tmp.tv_sec--;
+ tmp.tv_usec+=1000000;
+ }
+ data->start=tmp;
+ IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)
+}
+
+__inline void FORCE_TIME(struct timeval *src, struct time_conv *dest)
+{
+ dest->start=*src;
+}
+
+__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
+{
+ ULONGLONG tmp;
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, tmp
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+#else
+#endif
+ if (data->reference==0) {
+ return;
+ }
+ dst->tv_sec=(LONG)(tmp/data->reference);
+ dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);
+ dst->tv_sec+=data->start.tv_sec;
+ dst->tv_usec+=data->start.tv_usec;
+ if (dst->tv_usec>=1000000) {
+ dst->tv_sec++;
+ dst->tv_usec-=1000000;
+ }
+}
+
+#endif /*KQPC_TS*/
+
+#endif /*WIN_NT_DRIVER*/
+
+#endif /* __GNUC__ */
+
+#endif /*_time_calls*/
--- /dev/null
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+#include <net/tme/tme.h>
+#endif
+
+/* resizes extended memory */
+uint32 init_extended_memory(uint32 size, MEM_TYPE *mem_ex)
+{
+ uint8 *tmp;
+
+ if ((mem_ex==NULL)||(mem_ex->buffer==NULL)||(size==0))
+ return TME_ERROR; /* awfully never reached!!!! */
+
+ tmp=mem_ex->buffer;
+ mem_ex->buffer=NULL;
+ FREE_MEMORY(tmp);
+
+ ALLOCATE_MEMORY(tmp,uint8,size);
+ if (tmp==NULL)
+ return TME_ERROR; /* no memory */
+
+ mem_ex->size=size;
+ mem_ex->buffer=tmp;
+ return TME_SUCCESS;
+
+}
+
+/* activates a block of the TME */
+uint32 set_active_tme_block(TME_CORE *tme, uint32 block)
+{
+
+ if ((block>=MAX_TME_DATA_BLOCKS)||(!IS_VALIDATED(tme->validated_blocks,block)))
+ return TME_ERROR;
+ tme->active=block;
+ tme->working=block;
+ return TME_SUCCESS;
+
+}
+
+/* simply inserts default values in a TME block */
+/* it DOESN'T initialize the block in the core!! */
+/* FIXME default values are defined at compile time, */
+/* it will be useful to store them in the registry */
+uint32 init_tme_block(TME_CORE *tme, uint32 block)
+{
+
+ TME_DATA *data;
+ if (block>=MAX_TME_DATA_BLOCKS)
+ return TME_ERROR;
+ data=&(tme->block_data[block]);
+ tme->working=block;
+
+ ZERO_MEMORY(data,sizeof(TME_DATA));
+
+ /* entries in LUT */
+ data->lut_entries=TME_LUT_ENTRIES_DEFAULT;
+ /* blocks */
+ data->shared_memory_blocks=TME_SHARED_MEMORY_BLOCKS_DEFAULT;
+ /* block size */
+ data->block_size=TME_BLOCK_SIZE_DEFAULT;
+ /* lookup function */
+ data->lookup_code=lut_fcn_mapper(TME_LOOKUP_CODE_DEFAULT);
+ /* rehashing value */
+ data->rehashing_value=TME_REHASHING_VALUE_DEFAULT;
+ /* out lut function */
+ data->out_lut_exec=TME_OUT_LUT_EXEC_DEFAULT;
+ /* default function */
+ data->default_exec=TME_DEFAULT_EXEC_DEFAULT;
+ /* extra segment size */
+ data->extra_segment_size=TME_EXTRA_SEGMENT_SIZE_DEFAULT;
+
+
+ data->enable_deletion=FALSE;
+ data->last_read.tv_sec=0;
+ data->last_read.tv_usec=0;
+ return TME_SUCCESS;
+
+}
+/* it validates a TME block and */
+/* (on OK) inserts the block in the core */
+uint32 validate_tme_block(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 block, uint32 mem_ex_offset)
+{
+ uint32 required_memory;
+ uint8 *base=mem_ex_offset+mem_ex->buffer;
+ TME_DATA *data;
+
+ /* FIXME soluzione un po' posticcia... */
+ if (mem_ex_offset==0)
+ return TME_ERROR;
+
+ if (block>=MAX_TME_DATA_BLOCKS)
+ return TME_ERROR;
+ data=&tme->block_data[block];
+
+ if (data->lut_entries==0)
+ return TME_ERROR;
+
+ if (data->key_len==0)
+ return TME_ERROR;
+
+ if (data->shared_memory_blocks==0)
+ return TME_ERROR;
+
+ if (data->block_size==0)
+ return TME_ERROR;
+
+ /* checks if the lookup function is valid */
+ if (data->lookup_code==NULL)
+ return TME_ERROR;
+
+ /* checks if the out lut exec function is valid */
+ if (exec_fcn_mapper(data->out_lut_exec)==NULL)
+ return TME_ERROR;
+
+ /* checks if the default exec function is valid */
+ if (exec_fcn_mapper(data->default_exec)==NULL)
+ return TME_ERROR;
+
+ /* let's calculate memory needed */
+ required_memory=data->lut_entries*sizeof(RECORD); /*LUT*/
+ required_memory+=data->block_size*data->shared_memory_blocks; /*shared segment*/
+ required_memory+=data->extra_segment_size; /*extra segment*/
+
+ if (required_memory>(mem_ex->size-mem_ex_offset))
+ return TME_ERROR; /*not enough memory*/
+
+ /* the TME block can be initialized */
+ ZERO_MEMORY(base,required_memory);
+
+ data->lut_base_address=base;
+
+ data->shared_memory_base_address=
+ data->lut_base_address+
+ data->lut_entries*sizeof(RECORD);
+
+ data->extra_segment_base_address=
+ data->shared_memory_base_address+
+ data->block_size*data->shared_memory_blocks;
+ data->filled_blocks=1;
+ VALIDATE(tme->validated_blocks,block);
+ tme->active=block;
+ tme->working=block;
+ return TME_SUCCESS;
+}
+
+/* I/F between the bpf machine and the callbacks, just some checks */
+uint32 lookup_frontend(MEM_TYPE *mem_ex, TME_CORE *tme,uint32 mem_ex_offset, struct time_conv *time_ref)
+{
+ if (tme->active==TME_NONE_ACTIVE)
+ return TME_FALSE;
+
+ return (tme->block_data[tme->active].lookup_code)(mem_ex_offset+mem_ex->buffer,&tme->block_data[tme->active],mem_ex, time_ref);
+}
+
+/* I/F between the bpf machine and the callbacks, just some checks */
+uint32 execute_frontend(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 pkt_size, uint32 offset)
+{
+
+ exec_fcn tmp;
+ TME_DATA *data;
+ uint8 *block;
+ uint8 *mem_data;
+
+ if (tme->active==TME_NONE_ACTIVE)
+ return TME_ERROR;
+
+ data=&tme->block_data[tme->active];
+
+ if (data->last_found==NULL)
+ { /*out lut exec */
+ tmp=exec_fcn_mapper(data->out_lut_exec);
+ block=data->shared_memory_base_address;
+ }
+ else
+ { /*checks if last_found is valid */
+ if ((data->last_found<data->lut_base_address)||(data->last_found>=data->shared_memory_base_address))
+ return TME_ERROR;
+ else
+ {
+ tmp=exec_fcn_mapper(SW_ULONG_AT(&((RECORD*)data->last_found)->exec_fcn,0));
+ if (tmp==NULL)
+ return TME_ERROR;
+ block=SW_ULONG_AT(&((RECORD*)data->last_found)->block,0)+mem_ex->buffer;
+ if ((block<data->shared_memory_base_address)||(block>=data->extra_segment_base_address))
+ return TME_ERROR;
+ }
+ }
+
+ if (offset>=mem_ex->size)
+ return TME_ERROR;
+
+ mem_data=mem_ex->buffer+offset;
+
+ return tmp(block,pkt_size,data,mem_ex,mem_data);
+}
+
+/*resets all the TME core*/
+uint32 reset_tme(TME_CORE *tme)
+{
+ if (tme==NULL)
+ return TME_ERROR;
+ ZERO_MEMORY(tme, sizeof(TME_CORE));
+ return TME_SUCCESS;
+}
+
+/* returns a register value of the active TME block */
+/* FIXME last found in maniera elegante e veloce ?!?! */
+uint32 get_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 *rval)
+{
+ switch(rgstr)
+ {
+ case TME_LUT_ENTRIES:
+ *rval=data->lut_entries;
+ return TME_SUCCESS;
+ case TME_MAX_FILL_STATE:
+ *rval=data->max_fill_state;
+ return TME_SUCCESS;
+ case TME_REHASHING_VALUE:
+ *rval=data->rehashing_value;
+ return TME_SUCCESS;
+ case TME_KEY_LEN:
+ *rval=data->key_len;
+ return TME_SUCCESS;
+ case TME_SHARED_MEMORY_BLOCKS:
+ *rval=data->shared_memory_blocks;
+ return TME_SUCCESS;
+ case TME_FILLED_ENTRIES:
+ *rval=data->filled_entries;
+ return TME_SUCCESS;
+ case TME_BLOCK_SIZE:
+ *rval=data->block_size;
+ return TME_SUCCESS;
+ case TME_EXTRA_SEGMENT_SIZE:
+ *rval=data->extra_segment_size;
+ return TME_SUCCESS;
+ case TME_FILLED_BLOCKS:
+ *rval=data->filled_blocks;
+ return TME_SUCCESS;
+ case TME_DEFAULT_EXEC:
+ *rval=data->default_exec;
+ return TME_SUCCESS;
+ case TME_OUT_LUT_EXEC:
+ *rval=data->out_lut_exec;
+ return TME_SUCCESS;
+ case TME_SHARED_MEMORY_BASE_ADDRESS:
+ *rval=data->shared_memory_base_address-mem_ex->buffer;
+ return TME_SUCCESS;
+ case TME_LUT_BASE_ADDRESS:
+ *rval=data->lut_base_address-mem_ex->buffer;
+ return TME_SUCCESS;
+ case TME_EXTRA_SEGMENT_BASE_ADDRESS:
+ *rval=data->extra_segment_base_address-mem_ex->buffer;
+ return TME_SUCCESS;
+ case TME_LAST_FOUND_BLOCK:
+ if (data->last_found==NULL)
+ *rval=0;
+ else
+ *rval=data->last_found-mem_ex->buffer;
+ return TME_SUCCESS;
+
+ default:
+ return TME_ERROR;
+ }
+}
+
+/* sets a register value in the active block */
+/* FIXME last found in maniera elegante e veloce ?!?! */
+uint32 set_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 value, int32 init)
+{ /* very very very dangerous!!!!!!!!!!! */
+ lut_fcn tmp;
+ switch(rgstr)
+ {
+ case TME_MAX_FILL_STATE:
+ data->max_fill_state=value;
+ return TME_SUCCESS;
+ case TME_REHASHING_VALUE:
+ data->rehashing_value=value;
+ return TME_SUCCESS;
+ case TME_FILLED_ENTRIES:
+ data->filled_entries=value;
+ return TME_SUCCESS;
+ case TME_FILLED_BLOCKS:
+ if (value<=data->shared_memory_blocks)
+ {
+ data->filled_blocks=value;
+ return TME_SUCCESS;
+ }
+ else
+ return TME_ERROR;
+ case TME_DEFAULT_EXEC:
+ data->default_exec=value;
+ return TME_SUCCESS;
+ case TME_OUT_LUT_EXEC:
+ data->out_lut_exec=value;
+ return TME_SUCCESS;
+ case TME_LOOKUP_CODE:
+ tmp=lut_fcn_mapper(value);
+ if (tmp==NULL)
+ return TME_ERROR;
+ else
+ data->lookup_code=tmp;
+ return TME_SUCCESS;
+ default:
+ break;
+ }
+
+ if (init)
+ switch (rgstr)
+ {
+
+ case TME_LUT_ENTRIES:
+ data->lut_entries=value;
+ return TME_SUCCESS;
+ case TME_KEY_LEN:
+ data->key_len=value;
+ return TME_SUCCESS;
+ case TME_SHARED_MEMORY_BLOCKS:
+ data->shared_memory_blocks=value;
+ return TME_SUCCESS;
+ case TME_BLOCK_SIZE:
+ data->block_size=value;
+ return TME_SUCCESS;
+ case TME_EXTRA_SEGMENT_SIZE:
+ data->extra_segment_size=value;
+ return TME_SUCCESS;
+ default:
+ return TME_ERROR;
+ }
+ else
+ return TME_ERROR;
+
+}
+
+/* chooses the TME block for read */
+uint32 set_active_read_tme_block(TME_CORE *tme, uint32 block)
+{
+
+ if ((block>=MAX_TME_DATA_BLOCKS)||(!IS_VALIDATED(tme->validated_blocks,block)))
+ return TME_ERROR;
+ tme->active_read=block;
+ return TME_SUCCESS;
+
+}
+
+/* chooses if the autodeletion must be used */
+uint32 set_autodeletion(TME_DATA *data, uint32 value)
+{
+ if (value==0) /* no autodeletion */
+ data->enable_deletion=FALSE;
+ else
+ data->enable_deletion=TRUE;
+
+ return TME_SUCCESS;
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __tme_include_
+#define __tme_include_
+
+#ifdef WIN_NT_DRIVER
+
+#include "ntddk.h"
+#include "memory_t.h"
+#include "time_calls.h"
+#endif /*WIN_NT_DRIVER*/
+
+#ifdef WIN32
+#include "memory_t.h"
+#include "time_calls.h"
+#endif /*WIN32*/
+
+
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/time_calls.h>
+#else
+#include <tme/time_calls.h>
+#endif
+
+#endif
+
+/* error codes */
+#define TME_ERROR 0
+#define TME_SUCCESS 1
+#define TME_TRUE 2
+#define TME_FALSE 3
+
+/* some constants */
+#define DEFAULT_MEM_EX_SIZE 65536
+#define MAX_TME_DATA_BLOCKS 4
+#define TME_NONE_ACTIVE 0xffffffff
+#define DELTA_READ 2 /* secs */
+
+#define TME_LUT_ENTRIES 0x00000000
+#define TME_MAX_FILL_STATE 0x00000001 /*potrebbe servire per un thread a passive level!?!?! */
+#define TME_REHASHING_VALUE 0x00000002
+#define TME_KEY_LEN 0x00000003
+#define TME_SHARED_MEMORY_BLOCKS 0x00000004
+#define TME_FILLED_ENTRIES 0x00000005
+#define TME_BLOCK_SIZE 0x00000006
+#define TME_EXTRA_SEGMENT_SIZE 0x00000007
+#define TME_LOOKUP_CODE 0x00000008
+#define TME_OUT_LUT_EXEC 0x00000009
+#define TME_FILLED_BLOCKS 0x0000000a
+#define TME_DEFAULT_EXEC 0x0000000b
+#define TME_LUT_BASE_ADDRESS 0x0000000c
+#define TME_SHARED_MEMORY_BASE_ADDRESS 0x0000000d
+#define TME_EXTRA_SEGMENT_BASE_ADDRESS 0x0000000e
+#define TME_LAST_FOUND 0x0000000f /* contains the offset of the last found entry */
+#define TME_LAST_FOUND_BLOCK 0x00000010
+/* TME default values */
+#define TME_LUT_ENTRIES_DEFAULT 32007
+#define TME_REHASHING_VALUE_DEFAULT 1
+#define TME_SHARED_MEMORY_BLOCKS_DEFAULT 16000
+#define TME_BLOCK_SIZE_DEFAULT 64
+#define TME_EXTRA_SEGMENT_SIZE_DEFAULT 0
+#define TME_LOOKUP_CODE_DEFAULT 0
+#define TME_OUT_LUT_EXEC_DEFAULT 0
+#define TME_DEFAULT_EXEC_DEFAULT 0
+#define TME_MAX_FILL_STATE_DEFAULT 15000
+
+#define IS_VALIDATED(src,index) (src&(1<<index))
+
+#define VALIDATE(src,index) src|=(1<<index);
+
+
+#define FORCE_NO_DELETION(timestamp) (struct timeval*)(timestamp)->tv_sec=0x7fffffff;
+
+/* TME callback prototypes */
+#ifndef __GNUC__
+typedef uint32 (*lut_fcn)(uint8 *key, struct __TME_DATA *data,MEM_TYPE *mem_ex, struct time_conv *time_ref );
+typedef uint32 (*exec_fcn)(uint8 *block, uint32 pkt_size, struct __TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
+#else
+typedef uint32 (*lut_fcn)(uint8 *key, void *data,MEM_TYPE *mem_ex, struct time_conv *time_ref );
+typedef uint32 (*exec_fcn)(uint8 *block, uint32 pkt_size, void *data, MEM_TYPE *mem_ex, uint8 *mem_data);
+#endif
+
+/* DO NOT MODIFY THIS STRUCTURE!!!! GV */
+typedef struct __RECORD
+
+{
+ uint32 block;
+ uint32 exec_fcn;
+}
+ RECORD, *PRECORD;
+
+/* TME data registers */
+struct __TME_DATA
+{
+ uint32 lut_entries;
+ uint32 max_fill_state;
+ uint32 rehashing_value;
+ uint32 key_len;
+ uint32 shared_memory_blocks;
+ uint32 filled_entries;
+ uint32 block_size;
+ uint32 extra_segment_size;
+ uint32 filled_blocks;
+ lut_fcn lookup_code;
+ uint32 default_exec;
+ uint32 out_lut_exec;
+ uint8 *lut_base_address;
+ uint8 *shared_memory_base_address;
+ uint8 *extra_segment_base_address;
+ struct timeval last_read;
+ uint32 enable_deletion;
+ uint8 *last_found;
+};
+
+typedef struct __TME_DATA TME_DATA,*PTME_DATA;
+
+
+
+/* TME core */
+typedef struct __TME_CORE
+{
+ uint32 working;
+ uint32 active;
+ uint32 validated_blocks;
+ TME_DATA block_data[MAX_TME_DATA_BLOCKS];
+ uint32 active_read;
+
+} TME_CORE, *PTME_CORE;
+
+static __inline int32 IS_DELETABLE(void *timestamp, TME_DATA *data)
+{
+ struct timeval *ts=(struct timeval*)timestamp;
+
+ if (data->enable_deletion==FALSE)
+ return FALSE;
+ if (data->filled_entries<data->max_fill_state)
+ return FALSE;
+ if ((ts->tv_sec+DELTA_READ)<data->last_read.tv_sec)
+ return TRUE;
+ return FALSE;
+}
+
+/* functions to manage TME */
+uint32 init_tme_block(TME_CORE *tme, uint32 block);
+uint32 validate_tme_block(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 block, uint32 mem_ex_offset);
+uint32 lookup_frontend(MEM_TYPE *mem_ex, TME_CORE *tme,uint32 mem_ex_offset, struct time_conv *time_ref);
+uint32 execute_frontend(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 pkt_size,uint32 offset);
+uint32 set_active_tme_block(TME_CORE *tme, uint32 block);
+uint32 init_extended_memory(uint32 size, MEM_TYPE *mem_ex);
+uint32 reset_tme(TME_CORE *tme);
+uint32 get_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 *rval);
+uint32 set_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 value, int32 init);
+uint32 set_active_read_tme_block(TME_CORE *tme, uint32 block);
+uint32 set_autodeletion(TME_DATA *data, uint32 value);
+
+/* function mappers */
+lut_fcn lut_fcn_mapper(uint32 index);
+exec_fcn exec_fcn_mapper(uint32 index);
+
+#endif
\ No newline at end of file
--- /dev/null
+u_short valid_instructions[]=
+ {
+ BPF_RET|BPF_K,
+ BPF_RET|BPF_A,
+ BPF_LD|BPF_IMM,
+ BPF_LDX|BPF_IMM,
+ BPF_LD|BPF_MEM,
+ BPF_LDX|BPF_MEM,
+ BPF_LD|BPF_MEM_EX_IMM|BPF_B,
+ BPF_LD|BPF_MEM_EX_IMM|BPF_H,
+ BPF_LD|BPF_MEM_EX_IMM|BPF_W,
+ BPF_LD|BPF_MEM_EX_IND|BPF_B,
+ BPF_LD|BPF_MEM_EX_IND|BPF_H,
+ BPF_LD|BPF_MEM_EX_IND|BPF_W,
+ BPF_LD|BPF_W|BPF_ABS,
+ BPF_LD|BPF_H|BPF_ABS,
+ BPF_LD|BPF_B|BPF_ABS,
+ BPF_LDX|BPF_W|BPF_ABS,
+ BPF_LDX|BPF_H|BPF_ABS,
+ BPF_LDX|BPF_B|BPF_ABS,
+ BPF_LD|BPF_W|BPF_LEN,
+ BPF_LDX|BPF_W|BPF_LEN,
+ BPF_LD|BPF_W|BPF_IND,
+ BPF_LD|BPF_H|BPF_IND,
+ BPF_LD|BPF_B|BPF_IND,
+ BPF_LDX|BPF_MSH|BPF_B,
+ BPF_ST,
+ BPF_STX,
+ BPF_ST|BPF_MEM_EX_IMM|BPF_B,
+ BPF_STX|BPF_MEM_EX_IMM|BPF_B,
+ BPF_ST|BPF_MEM_EX_IMM|BPF_W,
+ BPF_STX|BPF_MEM_EX_IMM|BPF_W,
+ BPF_ST|BPF_MEM_EX_IMM|BPF_H,
+ BPF_STX|BPF_MEM_EX_IMM|BPF_H,
+ BPF_ST|BPF_MEM_EX_IND|BPF_B,
+ BPF_ST|BPF_MEM_EX_IND|BPF_W,
+ BPF_ST|BPF_MEM_EX_IND|BPF_H,
+ BPF_JMP|BPF_JA,
+ BPF_JMP|BPF_JGT|BPF_K,
+ BPF_JMP|BPF_JGE|BPF_K,
+ BPF_JMP|BPF_JEQ|BPF_K,
+ BPF_JMP|BPF_JSET|BPF_K,
+ BPF_JMP|BPF_JGT|BPF_X,
+ BPF_JMP|BPF_JGE|BPF_X,
+ BPF_JMP|BPF_JEQ|BPF_X,
+ BPF_JMP|BPF_JSET|BPF_X,
+ BPF_ALU|BPF_ADD|BPF_X,
+ BPF_ALU|BPF_SUB|BPF_X,
+ BPF_ALU|BPF_MUL|BPF_X,
+ BPF_ALU|BPF_DIV|BPF_X,
+ BPF_ALU|BPF_AND|BPF_X,
+ BPF_ALU|BPF_OR|BPF_X,
+ BPF_ALU|BPF_LSH|BPF_X,
+ BPF_ALU|BPF_RSH|BPF_X,
+ BPF_ALU|BPF_ADD|BPF_K,
+ BPF_ALU|BPF_SUB|BPF_K,
+ BPF_ALU|BPF_MUL|BPF_K,
+ BPF_ALU|BPF_DIV|BPF_K,
+ BPF_ALU|BPF_AND|BPF_K,
+ BPF_ALU|BPF_OR|BPF_K,
+ BPF_ALU|BPF_LSH|BPF_K,
+ BPF_ALU|BPF_RSH|BPF_K,
+ BPF_ALU|BPF_NEG,
+ BPF_MISC|BPF_TAX,
+ BPF_MISC|BPF_TXA,
+ BPF_MISC|BPF_TME|BPF_LOOKUP,
+ BPF_MISC|BPF_TME|BPF_EXECUTE,
+ BPF_MISC|BPF_TME|BPF_SET_ACTIVE,
+ BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE,
+ BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE
+ };
+
+#define VALID_INSTRUCTIONS_LEN (sizeof(valid_instructions)/sizeof(u_short))
--- /dev/null
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)bpf.h 7.1 (Berkeley) 5/7/91
+ *
+ * @(#) $Header$ (LBL)
+ */
+
+#ifndef BPF_MAJOR_VERSION
+
+/* BSD style release date */
+#define BPF_RELEASE 199606
+
+typedef UCHAR u_char;
+typedef USHORT u_short;
+typedef ULONG u_int;
+typedef LONG bpf_int32;
+typedef ULONG bpf_u_int32;
+typedef ULONG u_int32;
+
+#define BPF_MAXINSNS 512
+#define BPF_MAXBUFSIZE 0x8000
+#define BPF_MINBUFSIZE 32
+
+#include "time_calls.h"
+
+/*
+ * The instruction data structure.
+ */
+struct bpf_insn {
+ u_short code;
+ u_char jt;
+ u_char jf;
+ bpf_int32 k;
+};
+
+/*
+ * Structure for BIOCSETF.
+ */
+struct bpf_program {
+ u_int bf_len;
+ struct bpf_insn *bf_insns;
+};
+
+/*
+ * Struct returned by BIOCGSTATS.
+ */
+struct bpf_stat {
+ u_int bs_recv; /* number of packets received */
+ u_int bs_drop; /* number of packets dropped */
+};
+
+/*
+ * Struct return by BIOCVERSION. This represents the version number of
+ * the filter language described by the instruction encodings below.
+ * bpf understands a program iff kernel_major == filter_major &&
+ * kernel_minor >= filter_minor, that is, if the value returned by the
+ * running kernel has the same major number and a minor number equal
+ * equal to or less than the filter being downloaded. Otherwise, the
+ * results are undefined, meaning an error may be returned or packets
+ * may be accepted haphazardly.
+ * It has nothing to do with the source code version.
+ */
+struct bpf_version {
+ u_short bv_major;
+ u_short bv_minor;
+};
+/* Current version number of filter architecture. */
+#define BPF_MAJOR_VERSION 1
+#define BPF_MINOR_VERSION 1
+
+
+/*
+ * Structure prepended to each packet.
+ */
+struct bpf_hdr {
+ struct timeval bh_tstamp; /* time stamp */
+ bpf_u_int32 bh_caplen; /* length of captured portion */
+ bpf_u_int32 bh_datalen; /* original length of packet */
+ u_short bh_hdrlen; /* length of bpf header (this struct
+ plus alignment padding) */
+};
+
+/*
+ * Data-link level type codes.
+ */
+
+/*
+ * These are the types that are the same on all platforms; on other
+ * platforms, a <net/bpf.h> should be supplied that defines the additional
+ * DLT_* codes appropriately for that platform (the BSDs, for example,
+ * should not just pick up this version of "bpf.h"; they should also define
+ * the additional DLT_* codes used by their kernels, as well as the values
+ * defined here - and, if the values they use for particular DLT_ types
+ * differ from those here, they should use their values, not the ones
+ * here).
+ */
+#define DLT_NULL 0 /* no link-layer encapsulation */
+#define DLT_EN10MB 1 /* Ethernet (10Mb) */
+#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
+#define DLT_AX25 3 /* Amateur Radio AX.25 */
+#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
+#define DLT_CHAOS 5 /* Chaos */
+#define DLT_IEEE802 6 /* IEEE 802 Networks */
+#define DLT_ARCNET 7 /* ARCNET */
+#define DLT_SLIP 8 /* Serial Line IP */
+#define DLT_PPP 9 /* Point-to-point Protocol */
+#define DLT_FDDI 10 /* FDDI */
+
+/*
+ * These are values from the traditional libpcap "bpf.h".
+ * Ports of this to particular platforms should replace these definitions
+ * with the ones appropriate to that platform, if the values are
+ * different on that platform.
+ */
+#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */
+#define DLT_RAW 12 /* raw IP */
+
+/*
+ * These are values from BSD/OS's "bpf.h".
+ * These are not the same as the values from the traditional libpcap
+ * "bpf.h"; however, these values shouldn't be generated by any
+ * OS other than BSD/OS, so the correct values to use here are the
+ * BSD/OS values.
+ *
+ * Platforms that have already assigned these values to other
+ * DLT_ codes, however, should give these codes the values
+ * from that platform, so that programs that use these codes will
+ * continue to compile - even though they won't correctly read
+ * files of these types.
+ */
+#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */
+
+#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */
+
+/*
+ * This value is defined by NetBSD; other platforms should refrain from
+ * using it for other purposes, so that NetBSD savefiles with a link
+ * type of 50 can be read as this type on all platforms.
+ */
+#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */
+
+/*
+ * This value was defined by libpcap 0.5; platforms that have defined
+ * it with a different value should define it here with that value -
+ * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
+ * whatever value that happens to be, so programs will correctly
+ * handle files with that link type regardless of the value of
+ * DLT_C_HDLC.
+ *
+ * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
+ * compatibility with programs written for BSD/OS.
+ *
+ * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
+ * for source compatibility with programs written for libpcap 0.5.
+ */
+#define DLT_C_HDLC 104 /* Cisco HDLC */
+#define DLT_CHDLC DLT_C_HDLC
+
+/*
+ * Reserved for future use.
+ * Do not pick other numerical value for these unless you have also
+ * picked up the tcpdump.org top-of-CVS-tree version of "savefile.c",
+ * which will arrange that capture files for these DLT_ types have
+ * the same "network" value on all platforms, regardless of what
+ * value is chosen for their DLT_ type (thus allowing captures made
+ * on one platform to be read on other platforms, even if the two
+ * platforms don't use the same numerical values for all DLT_ types).
+ */
+#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
+
+/*
+ * Values between 106 and 107 are used in capture file headers as
+ * link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ new types.
+ */
+
+/*
+ * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
+ * that the AF_ type in the link-layer header is in network byte order.
+ *
+ * OpenBSD defines it as 12, but that collides with DLT_RAW, so we
+ * define it as 108 here. If OpenBSD picks up this file, it should
+ * define DLT_LOOP as 12 in its version, as per the comment above -
+ * and should not use 108 for any purpose.
+ */
+#define DLT_LOOP 108
+
+/*
+ * Values between 109 and 112 are used in capture file headers as
+ * link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ new types.
+ */
+
+/*
+ * This is for Linux cooked sockets.
+ */
+#define DLT_LINUX_SLL 113
+
+/*
+ * The instruction encodings.
+ */
+/* instruction classes */
+#define BPF_CLASS(code) ((code) & 0x07)
+#define BPF_LD 0x00
+#define BPF_LDX 0x01
+#define BPF_ST 0x02
+#define BPF_STX 0x03
+#define BPF_ALU 0x04
+#define BPF_JMP 0x05
+#define BPF_RET 0x06
+#define BPF_MISC 0x07
+
+/* ld/ldx fields */
+#define BPF_SIZE(code) ((code) & 0x18)
+#define BPF_W 0x00
+#define BPF_H 0x08
+#define BPF_B 0x10
+#define BPF_MODE(code) ((code) & 0xe0)
+#define BPF_IMM 0x00
+#define BPF_ABS 0x20
+#define BPF_IND 0x40
+#define BPF_MEM 0x60
+#define BPF_LEN 0x80
+#define BPF_MSH 0xa0
+
+/* alu/jmp fields */
+#define BPF_OP(code) ((code) & 0xf0)
+#define BPF_ADD 0x00
+#define BPF_SUB 0x10
+#define BPF_MUL 0x20
+#define BPF_DIV 0x30
+#define BPF_OR 0x40
+#define BPF_AND 0x50
+#define BPF_LSH 0x60
+#define BPF_RSH 0x70
+#define BPF_NEG 0x80
+#define BPF_JA 0x00
+#define BPF_JEQ 0x10
+#define BPF_JGT 0x20
+#define BPF_JGE 0x30
+#define BPF_JSET 0x40
+#define BPF_SRC(code) ((code) & 0x08)
+#define BPF_K 0x00
+#define BPF_X 0x08
+
+/* ret - BPF_K and BPF_X also apply */
+#define BPF_RVAL(code) ((code) & 0x18)
+#define BPF_A 0x10
+
+/* misc */
+#define BPF_MISCOP(code) ((code) & 0xf8)
+#define BPF_TAX 0x00
+#define BPF_TXA 0x80
+
+/* TME instructions */
+#define BPF_TME 0x08
+
+#define BPF_LOOKUP 0x90
+#define BPF_EXECUTE 0xa0
+#define BPF_INIT 0xb0
+#define BPF_VALIDATE 0xc0
+#define BPF_SET_ACTIVE 0xd0
+#define BPF_RESET 0xe0
+#define BPF_SET_MEMORY 0x80
+#define BPF_GET_REGISTER_VALUE 0x70
+#define BPF_SET_REGISTER_VALUE 0x60
+#define BPF_SET_WORKING 0x50
+#define BPF_SET_ACTIVE_READ 0x40
+#define BPF_SET_AUTODELETION 0x30
+#define BPF_SEPARATION 0xff
+
+#define BPF_MEM_EX_IMM 0xc0
+#define BPF_MEM_EX_IND 0xe0
+/*used for ST */
+#define BPF_MEM_EX 0xc0
+
+
+/*
+ * Macros for insn array initializers.
+ */
+#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
+#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
+
+/*
+ * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
+ */
+#define BPF_MEMWORDS 16
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 1999, 2000
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *
+ *
+ * Portions copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+
+ @(#)bpf.c 7.5 (Berkeley) 7/15/91
+*/
+
+#include "tme.h"
+#include "win_bpf.h"
+
+#include "debug.h"
+
+#include "valid_insns.h"
+
+#define EXTRACT_SHORT(p)\
+ ((u_short)\
+ ((u_short)*((u_char *)p+0)<<8|\
+ (u_short)*((u_char *)p+1)<<0))
+#define EXTRACT_LONG(p)\
+ ((u_int32)*((u_char *)p+0)<<24|\
+ (u_int32)*((u_char *)p+1)<<16|\
+ (u_int32)*((u_char *)p+2)<<8|\
+ (u_int32)*((u_char *)p+3)<<0)
+
+
+u_int bpf_filter(pc, p, wirelen, buflen,mem_ex,tme,time_ref)
+ register struct bpf_insn *pc;
+ register u_char *p;
+ u_int wirelen;
+ register u_int buflen;
+ PMEM_TYPE mem_ex;
+ PTME_CORE tme;
+ struct time_conv *time_ref;
+
+{
+ register u_int32 A, X;
+ register int k;
+ u_int32 j,tmp;
+ u_short tmp2;
+
+ int32 mem[BPF_MEMWORDS];
+
+ if (pc == 0)
+ /*
+ * No filter means accept all.
+ */
+ return (u_int)-1;
+ A = 0;
+ X = 0;
+ --pc;
+ while (1) {
+ ++pc;
+ switch (pc->code) {
+
+ default:
+
+ return 0;
+
+ case BPF_RET|BPF_K:
+ return (u_int)pc->k;
+
+ case BPF_RET|BPF_A:
+ return (u_int)A;
+
+ case BPF_LD|BPF_W|BPF_ABS:
+ k = pc->k;
+ if (k + sizeof(int32) > buflen) {
+ return 0;
+ }
+ A = EXTRACT_LONG(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+ k = pc->k;
+ if (k + sizeof(short) > buflen) {
+ return 0;
+ }
+ A = EXTRACT_SHORT(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+ k = pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+ A = p[k];
+ continue;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+ A = wirelen;
+ continue;
+
+ case BPF_LDX|BPF_W|BPF_LEN:
+ X = wirelen;
+ continue;
+
+ case BPF_LD|BPF_W|BPF_IND:
+ k = X + pc->k;
+ if (k + sizeof(int32) > buflen) {
+ return 0;
+ }
+ A = EXTRACT_LONG(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_H|BPF_IND:
+ k = X + pc->k;
+ if (k + sizeof(short) > buflen) {
+ return 0;
+ }
+ A = EXTRACT_SHORT(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_B|BPF_IND:
+ k = X + pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+ A = p[k];
+ continue;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+ k = pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+ X = (p[pc->k] & 0xf) << 2;
+ continue;
+
+ case BPF_LD|BPF_IMM:
+ A = pc->k;
+ continue;
+
+ case BPF_LDX|BPF_IMM:
+ X = pc->k;
+ continue;
+
+ case BPF_LD|BPF_MEM:
+ A = mem[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM:
+ X = mem[pc->k];
+ continue;
+
+/* LD NO PACKET INSTRUCTIONS */
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
+ A= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
+ X= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
+ A = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
+ X = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
+ A = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
+ X = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_B:
+ k = X + pc->k;
+ if ((int32)k>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A= mem_ex->buffer[k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_H:
+ k = X + pc->k;
+ if ((int32)(k+1)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A=EXTRACT_SHORT((uint32*)&mem_ex->buffer[k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_W:
+ k = X + pc->k;
+ if ((int32)(k+3)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A=EXTRACT_LONG((uint32*)&mem_ex->buffer[k]);
+ continue;
+/* END LD NO PACKET INSTRUCTIONS */
+
+ case BPF_ST:
+ mem[pc->k] = A;
+ continue;
+
+ case BPF_STX:
+ mem[pc->k] = X;
+ continue;
+
+/* STORE INSTRUCTIONS */
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)A;
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)X;
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
+ tmp=A;
+ *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
+ tmp=X;
+ *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16)A;
+ *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16)X;
+ *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_B:
+ mem_ex->buffer[pc->k+X]=(uint8)A;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_W:
+ tmp=A;
+ *(uint32*)&mem_ex->buffer[pc->k+X]=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_H:
+ tmp2=(uint16)A;
+ *(uint16*)&mem_ex->buffer[pc->k+X]=EXTRACT_SHORT(&tmp2);
+ continue;
+/* END STORE INSTRUCTIONS */
+
+ case BPF_JMP|BPF_JA:
+ pc += pc->k;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ pc += ((int)A > (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ pc += ((int)A >= (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ pc += ((int)A == (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ pc += (A & pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ pc += (A > X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ pc += (A >= X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ pc += (A == X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ pc += (A & X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+ A += X;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ A -= X;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ A *= X;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ if (X == 0)
+ return 0;
+ A /= X;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ A &= X;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ A |= X;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ A <<= X;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ A >>= X;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ A += pc->k;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ A -= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ A *= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ A /= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ A &= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ A |= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ A <<= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ A >>= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_NEG:
+ (int)A = -((int)A);
+ continue;
+
+ case BPF_MISC|BPF_TAX:
+ X = A;
+ continue;
+
+ case BPF_MISC|BPF_TXA:
+ A = X;
+ continue;
+
+/* TME INSTRUCTIONS */
+ case BPF_MISC|BPF_TME|BPF_LOOKUP:
+ j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
+ if (j==TME_ERROR)
+ return 0;
+ pc += (j == TME_TRUE) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_EXECUTE:
+ if (execute_frontend(mem_ex,tme,wirelen,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
+ if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
+ if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
+ return 0;
+ A=j;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
+ if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,FALSE)==TME_ERROR)
+ return 0;
+ continue;
+/* END TME INSTRUCTIONS */
+
+ }
+ }
+}
+
+//-------------------------------------------------------------------
+
+u_int bpf_filter_with_2_buffers(pc, p, pd, headersize, wirelen, buflen, mem_ex,tme,time_ref)
+ register struct bpf_insn *pc;
+ register u_char *p;
+ register u_char *pd;
+ register int headersize;
+ u_int wirelen;
+ register u_int buflen;
+ PMEM_TYPE mem_ex;
+ PTME_CORE tme;
+ struct time_conv *time_ref;
+{
+ register u_int32 A, X;
+ register int k;
+ int32 mem[BPF_MEMWORDS];
+ u_int32 j,tmp;
+ u_short tmp2;
+
+ if (pc == 0)
+ /*
+ * No filter means accept all.
+ */
+ return (u_int)-1;
+ A = 0;
+ X = 0;
+ --pc;
+ while (1) {
+ ++pc;
+ switch (pc->code) {
+
+ default:
+
+ return 0;
+
+ case BPF_RET|BPF_K:
+ return (u_int)pc->k;
+
+ case BPF_RET|BPF_A:
+ return (u_int)A;
+
+ case BPF_LD|BPF_W|BPF_ABS:
+ k = pc->k;
+ if (k + sizeof(int32) > buflen) {
+ return 0;
+ }
+
+ if(k + (int)sizeof(int32) < headersize) A = EXTRACT_LONG(&p[k]);
+ else if(k + 2 == headersize){
+ A=(u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)p+k+1)<<16|
+ (u_int32)*((u_char *)p+k+2)<<8|
+ (u_int32)*((u_char *)pd+k-headersize);
+ }
+ else if(k == headersize-1){
+ A=(u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)p+k+1)<<16|
+ (u_int32)*((u_char *)pd+k-headersize)<<8|
+ (u_int32)*((u_char *)pd+k-headersize+1);
+ }
+ else if(k == headersize){
+ A=(u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)pd+k-headersize+1)<<16|
+ (u_int32)*((u_char *)pd+k-headersize+2)<<8|
+ (u_int32)*((u_char *)pd+k-headersize+3);
+ }
+ A = EXTRACT_LONG(&pd[k-headersize]);
+
+ continue;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+ k = pc->k;
+ if (k + sizeof(short) > buflen) {
+ return 0;
+ }
+
+ if(k + (int)sizeof(short) < headersize) A = EXTRACT_SHORT(&p[k]);
+ else if(k == headersize){
+ A=(u_short)*((u_char *)p+k)<<8|
+ (u_short)*((u_char *)pd+k-headersize);
+ }
+ A = EXTRACT_SHORT(&pd[k-headersize]);
+
+ continue;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+ k = pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+
+ if(k<headersize) A = p[k];
+ else A = pd[k-headersize];
+
+ continue;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+ A = wirelen;
+ continue;
+
+ case BPF_LDX|BPF_W|BPF_LEN:
+ X = wirelen;
+ continue;
+
+ case BPF_LD|BPF_W|BPF_IND:
+ k = X + pc->k;
+ if (k + sizeof(int32) > buflen) {
+ return 0;
+ }
+
+ if(k + (int)sizeof(int32) < headersize) A = EXTRACT_LONG(&p[k]);
+ else if(k + (int)sizeof(int32) == headersize+2){
+ A=(u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)p+k+1)<<16|
+ (u_int32)*((u_char *)p+k+2)<<8|
+ (u_int32)*((u_char *)pd+k-headersize);
+ }
+ else if(k + (int)sizeof(int32) == headersize+3){
+ A=(u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)p+k+1)<<16|
+ (u_int32)*((u_char *)pd+k-headersize)<<8|
+ (u_int32)*((u_char *)pd+k-headersize+1);
+ }
+ else if(k + (int)sizeof(int32) == headersize+4){
+ A=(u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)pd+k-headersize+1)<<16|
+ (u_int32)*((u_char *)pd+k-headersize+2)<<8|
+ (u_int32)*((u_char *)pd+k-headersize+3);
+ }
+ A = EXTRACT_LONG(&pd[k-headersize]);
+
+ continue;
+
+ case BPF_LD|BPF_H|BPF_IND:
+ k = X + pc->k;
+ if (k + sizeof(short) > buflen) {
+ return 0;
+ }
+
+ if(k + (int)sizeof(short) < headersize) A = EXTRACT_SHORT(&p[k]);
+ else if(k == headersize){
+ A=(u_short)*((u_char *)p+k)<<8|
+ (u_short)*((u_char *)pd+k-headersize);
+ }
+ A = EXTRACT_SHORT(&pd[k-headersize]);
+
+ continue;
+
+ case BPF_LD|BPF_B|BPF_IND:
+ k = X + pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+
+ if(k<headersize) A = p[k];
+ else A = pd[k-headersize];
+
+ continue;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+ k = pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+
+ if((pc->k)<headersize) X = (p[pc->k] & 0xf) << 2;
+ else X = (pd[(pc->k)-headersize] & 0xf) << 2;
+
+ continue;
+
+ case BPF_LD|BPF_IMM:
+ A = pc->k;
+ continue;
+
+ case BPF_LDX|BPF_IMM:
+ X = pc->k;
+ continue;
+
+ case BPF_LD|BPF_MEM:
+ A = mem[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM:
+ X = mem[pc->k];
+ continue;
+
+/* LD NO PACKET INSTRUCTIONS */
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
+ A= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
+ X= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
+ A = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
+ X = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
+ A = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
+ X = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_B:
+ k = X + pc->k;
+ if ((int32)k>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A= mem_ex->buffer[k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_H:
+ k = X + pc->k;
+ if ((int32)(k+1)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A=EXTRACT_SHORT((uint32*)&mem_ex->buffer[k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_W:
+ k = X + pc->k;
+ if ((int32)(k+3)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A=EXTRACT_LONG((uint32*)&mem_ex->buffer[k]);
+ continue;
+/* END LD NO PACKET INSTRUCTIONS */
+
+ case BPF_ST:
+ mem[pc->k] = A;
+ continue;
+
+ case BPF_STX:
+ mem[pc->k] = X;
+ continue;
+
+
+/* STORE INSTRUCTIONS */
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)A;
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)X;
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
+ tmp=A;
+ *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
+ tmp=X;
+ *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16)A;
+ *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16)X;
+ *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_B:
+ mem_ex->buffer[pc->k+X]=(uint8)A;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_W:
+ tmp=A;
+ *(uint32*)&mem_ex->buffer[pc->k+X]=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_H:
+ tmp2=(uint16)A;
+ *(uint16*)&mem_ex->buffer[pc->k+X]=EXTRACT_SHORT(&tmp2);
+ continue;
+/* END STORE INSTRUCTIONS */
+
+
+
+ case BPF_JMP|BPF_JA:
+ pc += pc->k;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ pc += ((int)A > (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ pc += ((int)A >= (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ pc += ((int)A == (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ pc += (A & pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ pc += (A > X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ pc += (A >= X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ pc += (A == X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ pc += (A & X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+ A += X;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ A -= X;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ A *= X;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ if (X == 0)
+ return 0;
+ A /= X;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ A &= X;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ A |= X;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ A <<= X;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ A >>= X;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ A += pc->k;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ A -= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ A *= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ A /= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ A &= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ A |= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ A <<= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ A >>= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_NEG:
+ (int)A = -((int)A);
+ continue;
+
+ case BPF_MISC|BPF_TAX:
+ X = A;
+ continue;
+
+ case BPF_MISC|BPF_TXA:
+ A = X;
+ continue;
+
+/* TME INSTRUCTIONS */
+ case BPF_MISC|BPF_TME|BPF_LOOKUP:
+ j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
+ if (j==TME_ERROR)
+ return 0;
+ pc += (j == TME_TRUE) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_EXECUTE:
+ if (execute_frontend(mem_ex,tme,wirelen,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
+ if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
+ if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
+ return 0;
+ A=j;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
+ if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,FALSE)==TME_ERROR)
+ return 0;
+ continue;
+/* END TME INSTRUCTIONS */
+
+ }
+ }
+}
+
+int32
+bpf_validate(f, len,mem_ex_size)
+ struct bpf_insn *f;
+ int32 len;
+ uint32 mem_ex_size;
+{
+ register int32 i,j;
+ register struct bpf_insn *p;
+ int32 flag;
+
+ for (i = 0; i < len; ++i) {
+ /*
+ * Check that that jumps are forward, and within
+ * the code block.
+ */
+
+ p = &f[i];
+
+ IF_LOUD(DbgPrint("Validating program");)
+
+ flag=0;
+ for(j=0;j<VALID_INSTRUCTIONS_LEN;j++)
+ if (p->code==valid_instructions[j])
+ flag=1;
+ if (flag==0)
+ return 0;
+
+ IF_LOUD(DbgPrint("Validating program: no unknown instructions");)
+
+ if (BPF_CLASS(p->code) == BPF_JMP) {
+ register int32 from = i + 1;
+
+ if (BPF_OP(p->code) == BPF_JA) {
+ if (from + p->k >= len)
+ return 0;
+ }
+ else if (from + p->jt >= len || from + p->jf >= len)
+ return 0;
+ }
+
+ IF_LOUD(DbgPrint("Validating program: no wrong JUMPS");)
+
+ /*
+ * Check that memory operations use valid addresses.
+ */
+ if (((BPF_CLASS(p->code) == BPF_ST && ((p->code &BPF_MEM_EX_IMM)!=BPF_MEM_EX_IMM && (p->code &BPF_MEM_EX_IND)!=BPF_MEM_EX_IND)) ||
+ (BPF_CLASS(p->code) == BPF_LD &&
+ (p->code & 0xe0) == BPF_MEM)) &&
+ (p->k >= BPF_MEMWORDS || p->k < 0))
+ return 0;
+
+ IF_LOUD(DbgPrint("Validating program: no wrong ST/LD memory locations");)
+
+ /*
+ * Check if key stores use valid addresses
+ */
+ if (BPF_CLASS(p->code) == BPF_ST && (p->code &BPF_MEM_EX_IMM)==BPF_MEM_EX_IMM)
+ switch (BPF_SIZE(p->code))
+ {
+ case BPF_W: if (p->k<0 || p->k+3>=(int32)mem_ex_size) return 0;
+ case BPF_H: if (p->k<0 || p->k+1>=(int32)mem_ex_size) return 0;
+ case BPF_B: if (p->k<0 || p->k>=(int32)mem_ex_size) return 0;
+ }
+
+ IF_LOUD(DbgPrint("Validating program: no wrong ST/LD mem_ex locations");)
+
+ /*
+ * Check for constant division by 0.
+ */
+ if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
+ return 0;
+ }
+ return BPF_CLASS(f[len - 1].code) == BPF_RET;
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *
+ *
+ * Portions copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "tme.h"
+#include "win_bpf.h"
+
+/*
+ * Initialize the filter machine
+ */
+uint32 bpf_filter_init(register struct bpf_insn *pc, MEM_TYPE *mem_ex, TME_CORE *tme, struct time_conv *time_ref)
+{
+ register uint32 A, X;
+ int32 mem[BPF_MEMWORDS];
+ register int32 k;
+ uint32 *tmp;
+ uint16 *tmp2;
+ uint32 j;
+ if (pc == 0)
+ /*
+ * No filter means accept all.
+ */
+ return (uint32)-1;
+ A = 0;
+ X = 0;
+ --pc;
+ while (1) {
+ ++pc;
+ switch (pc->code) {
+
+ default:
+ return 0;
+
+/* RET INSTRUCTIONS */
+ case BPF_RET|BPF_K:
+ return (uint32)pc->k;
+
+ case BPF_RET|BPF_A:
+ return (uint32)A;
+/* END RET INSTRUCTIONS */
+
+/* LD NO PACKET INSTRUCTIONS */
+ case BPF_LD|BPF_IMM:
+ A = pc->k;
+ continue;
+
+ case BPF_LDX|BPF_IMM:
+ X = pc->k;
+ continue;
+
+ case BPF_LD|BPF_MEM:
+ A = mem[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM:
+ X = mem[pc->k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
+ A= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
+ X= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k];
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp2
+ xor eax, eax
+ mov ax, [ebx]
+ bswap eax
+ mov A, eax
+ pop ebx
+ pop eax
+ }
+#else
+ asm("push %%eax;"
+ "push %%ebx;"
+ "mov %1,%%ebx;"
+ "xor %%eax, %%eax;"
+ "mov (%%ebx), %%ax;"
+ "bswap %%eax;"
+ "mov %%eax, %0;"
+ "pop %%ebx;"
+ "pop %%eax;"
+ :"=a"(A),"=c"(tmp2): );
+#endif
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k];
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp2
+ xor eax, eax
+ mov ax, [ebx]
+ bswap eax
+ mov X, eax
+ pop ebx
+ pop eax
+ }
+#else
+ asm("push %%eax;"
+ "push %%ebx;"
+ "mov %1,%%ebx;"
+ "xor %%eax, %%eax;"
+ "mov (%%ebx), %%ax;"
+ "bswap %%eax;"
+ "mov %%eax, %0;"
+ "pop %%ebx;"
+ "pop %%eax;"
+ :"=a"(X),"=c"(tmp2): );
+#endif
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k];
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp
+ mov eax, [ebx]
+ bswap eax
+ mov A, eax
+ pop ebx
+ pop eax
+ }
+#else
+ asm("push %%eax;"
+ "push %%ebx;"
+ "mov %1,%%ebx;"
+ "xor %%eax, %%eax;"
+ "mov (%%ebx), %%ax;"
+ "bswap %%eax;"
+ "mov %%eax, %0;"
+ "pop %%ebx;"
+ "pop %%eax;"
+ :"=a"(A),"=c"(tmp): );
+#endif
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k];
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp
+ mov eax, [ebx]
+ bswap eax
+ mov X, eax
+ pop ebx
+ pop eax
+ }
+#else
+ asm("push %%eax;"
+ "push %%ebx;"
+ "mov %1,%%ebx;"
+ "xor %%eax, %%eax;"
+ "mov (%%ebx), %%ax;"
+ "bswap %%eax;"
+ "mov %%eax, %0;"
+ "pop %%ebx;"
+ "pop %%eax;"
+ :"=a"(X),"=c"(tmp): );
+#endif
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_B:
+ k = X + pc->k;
+ if ((int32)k>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A= mem_ex->buffer[k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_H:
+ k = X + pc->k;
+ if ((int32)(k+1)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ tmp2=(uint16*)&mem_ex->buffer[k];
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp2
+ xor eax, eax
+ mov ax, [ebx]
+ bswap eax
+ mov A, eax
+ pop ebx
+ pop eax
+ }
+#else
+ asm("push %%eax;"
+ "push %%ebx;"
+ "mov %1,%%ebx;"
+ "xor %%eax, %%eax;"
+ "mov (%%ebx), %%ax;"
+ "bswap %%eax;"
+ "mov %%eax, %0;"
+ "pop %%ebx;"
+ "pop %%eax;"
+ :"=a"(A),"=c"(tmp2): );
+#endif
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_W:
+ k = X + pc->k;
+ if ((int32)(k+3)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ tmp=(uint32*)&mem_ex->buffer[k];
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp
+ mov eax, [ebx]
+ bswap eax
+ mov A, eax
+ pop ebx
+ pop eax
+ }
+#else
+ asm("push %%eax;"
+ "push %%ebx;"
+ "mov %1,%%ebx;"
+ "xor %%eax, %%eax;"
+ "mov (%%ebx), %%ax;"
+ "bswap %%eax;"
+ "mov %%eax, %0;"
+ "pop %%ebx;"
+ "pop %%eax;"
+ :"=a"(A),"=c"(tmp): );
+#endif
+ continue;
+/* END LD NO PACKET INSTRUCTIONS */
+
+/* STORE INSTRUCTIONS */
+ case BPF_ST:
+ mem[pc->k] = A;
+ continue;
+
+ case BPF_STX:
+ mem[pc->k] = X;
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)A;
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)X;
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k];
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp
+ mov eax, A
+ bswap eax
+ mov [ebx], eax
+ pop ebx
+ pop eax
+ }
+#else
+ asm("push %%eax;"
+ "push %%ebx;"
+ "mov %1,%%ebx;"
+ "xor %%eax, %%eax;"
+ "mov (%%ebx), %%ax;"
+ "bswap %%eax;"
+ "mov %%eax, %0;"
+ "pop %%ebx;"
+ "pop %%eax;"
+ :"=a"(A),"=c"(tmp): );
+#endif
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k];
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp
+ mov eax, X
+ bswap eax
+ mov [ebx], eax
+ pop ebx
+ pop eax
+ }
+#else
+ asm("push %%eax;"
+ "push %%ebx;"
+ "mov %1,%%ebx;"
+ "xor %%eax, %%eax;"
+ "mov (%%ebx), %%ax;"
+ "bswap %%eax;"
+ "mov %%eax, %0;"
+ "pop %%ebx;"
+ "pop %%eax;"
+ :"=a"(X),"=c"(tmp): );
+#endif
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k];
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp2
+ mov eax, A
+ xchg ah, al
+ mov [ebx], ax
+ pop ebx
+ pop eax
+ }
+#else
+ asm("push %%eax;"
+ "push %%ebx;"
+ "mov %1,%%ebx;"
+ "xor %%eax, %%eax;"
+ "mov (%%ebx), %%ax;"
+ "bswap %%eax;"
+ "mov %%eax, %0;"
+ "pop %%ebx;"
+ "pop %%eax;"
+ :"=a"(A),"=c"(tmp2): );
+#endif
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k];
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp2
+ mov eax, X
+ xchg ah, al
+ mov [ebx], ax
+ pop ebx
+ pop eax
+ }
+#else
+ asm("push %%eax;"
+ "push %%ebx;"
+ "mov %1,%%ebx;"
+ "xor %%eax, %%eax;"
+ "mov (%%ebx), %%ax;"
+ "bswap %%eax;"
+ "mov %%eax, %0;"
+ "pop %%ebx;"
+ "pop %%eax;"
+ :"=a"(X),"=c"(tmp2): );
+#endif
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_B:
+ mem_ex->buffer[pc->k+X]=(uint8)A;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k+X];
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp
+ mov eax, A
+ bswap eax
+ mov [ebx], eax
+ pop ebx
+ pop eax
+ }
+#else
+ asm("push %%eax;"
+ "push %%ebx;"
+ "mov %1,%%ebx;"
+ "xor %%eax, %%eax;"
+ "mov (%%ebx), %%ax;"
+ "bswap %%eax;"
+ "mov %%eax, %0;"
+ "pop %%ebx;"
+ "pop %%eax;"
+ :"=a"(A),"=c"(tmp): );
+#endif
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k+X];
+#ifndef __GNUC__
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp2
+ mov eax, A
+ xchg ah, al
+ mov [ebx], ax
+ pop ebx
+ pop eax
+ }
+#else
+ asm("push %%eax;"
+ "push %%ebx;"
+ "mov %1,%%ebx;"
+ "xor %%eax, %%eax;"
+ "mov (%%ebx), %%ax;"
+ "bswap %%eax;"
+ "mov %%eax, %0;"
+ "pop %%ebx;"
+ "pop %%eax;"
+ :"=a"(A),"=c"(tmp2): );
+#endif
+ continue;
+/* END STORE INSTRUCTIONS */
+
+/* JUMP INSTRUCTIONS */
+ case BPF_JMP|BPF_JA:
+ pc += pc->k;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ pc += ((int32)A > (int32)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ pc += ((int32)A >= (int32)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ pc += ((int32)A == (int32)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ pc += (A & pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ pc += (A > X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ pc += (A >= X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ pc += (A == X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ pc += (A & X) ? pc->jt : pc->jf;
+ continue;
+/* END JUMP INSTRUCTIONS */
+
+/* ARITHMETIC INSTRUCTIONS */
+ case BPF_ALU|BPF_ADD|BPF_X:
+ A += X;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ A -= X;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ A *= X;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ if (X == 0)
+ return 0;
+ A /= X;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ A &= X;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ A |= X;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ A <<= X;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ A >>= X;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ A += pc->k;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ A -= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ A *= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ A /= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ A &= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ A |= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ A <<= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ A >>= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_NEG:
+ (int32)A = -((int32)A);
+ continue;
+/* ARITHMETIC INSTRUCTIONS */
+
+/* MISC INSTRUCTIONS */
+ case BPF_MISC|BPF_TAX:
+ X = A;
+ continue;
+
+ case BPF_MISC|BPF_TXA:
+ A = X;
+ continue;
+/* END MISC INSTRUCTIONS */
+
+/* TME INSTRUCTIONS */
+ case BPF_MISC|BPF_TME|BPF_LOOKUP:
+ j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
+ if (j==TME_ERROR)
+ return 0;
+ pc += (j == TME_TRUE) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_EXECUTE:
+ if (execute_frontend(mem_ex,tme,0,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_INIT:
+ if (init_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_VALIDATE:
+ if (validate_tme_block(mem_ex,tme,A,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_MEMORY:
+ if (init_extended_memory(pc->k,mem_ex)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
+ if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_ACTIVE_READ:
+ if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+ case BPF_MISC|BPF_TME|BPF_SET_WORKING:
+ if ((pc->k<0)||(pc->k>=MAX_TME_DATA_BLOCKS))
+ return 0;
+ tme->working=pc->k;
+ continue;
+
+
+
+ case BPF_MISC|BPF_TME|BPF_RESET:
+ if (reset_tme(tme)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
+ if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
+ return 0;
+ A=j;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
+ if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,TRUE)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_AUTODELETION:
+ set_autodeletion(&tme->block_data[tme->working],pc->k);
+ continue;
+
+/* END TME INSTRUCTIONS */
+
+ }
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2001
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef __FILTER_INIT
+#define __FILTER_INIT
+
+#include "tme.h"
+
+#define INIT_OK 1
+#define INIT_ERROR 0
+
+uint32 bpf_filter_init(register struct bpf_insn *pc,MEM_TYPE *mem_ex, TME_CORE *tme, struct time_conv *time_ref);
+
+#endif
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 1999, 2000
+ * Politecnico di Torino. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef _MSC_VER
+#include "stdarg.h"
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+#else
+#include <ddk/ntddk.h>
+#include <net/ndis.h>
+#define NdisReinitializePacket(Packet) \
+{ \
+ (Packet)->Private.Head = (PNDIS_BUFFER)NULL; \
+ (Packet)->Private.ValidCounts = FALSE; \
+}
+
+#endif
+
+#include "debug.h"
+#include "packet.h"
+
+
+//-------------------------------------------------------------------
+
+NTSTATUS STDCALL
+NPF_Write(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ )
+
+{
+ POPEN_INSTANCE Open;
+ PIO_STACK_LOCATION IrpSp;
+ PNDIS_PACKET pPacket;
+ UINT i;
+ NDIS_STATUS Status;
+
+ IF_LOUD(DbgPrint("NPF_Write\n");)
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+
+ Open=IrpSp->FileObject->FsContext;
+
+ IF_LOUD(DbgPrint("Max frame size = %d\n", Open->MaxFrameSize);)
+
+
+ if(IrpSp->Parameters.Write.Length == 0 || // Check that the buffer provided by the user is not empty
+ Open->MaxFrameSize == 0 || // Check that the MaxFrameSize is correctly initialized
+ IrpSp->Parameters.Write.Length > Open->MaxFrameSize) // Check that the fame size is smaller that the MTU
+ {
+ IF_LOUD(DbgPrint("frame size out of range, send aborted\n");)
+
+ Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
+ IoCompleteRequest (Irp, IO_NO_INCREMENT);
+ return NDIS_STATUS_SUCCESS;
+ }
+
+
+ IoMarkIrpPending(Irp);
+
+ Open->Multiple_Write_Counter=Open->Nwrites;
+
+ NdisResetEvent(&Open->WriteEvent);
+
+
+ for(i=0;i<Open->Nwrites;i++){
+
+ // Try to get a packet from our list of free ones
+ NdisAllocatePacket(
+ &Status,
+ &pPacket,
+ Open->PacketPool
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ // No free packets
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest (Irp, IO_NO_INCREMENT);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ // The packet has a buffer that needs not to be freed after every single write
+ RESERVED(pPacket)->FreeBufAfterWrite = FALSE;
+
+ // Save the IRP associated with the packet
+ RESERVED(pPacket)->Irp=Irp;
+
+ // Attach the writes buffer to the packet
+ NdisChainBufferAtFront(pPacket,Irp->MdlAddress);
+
+ // Call the MAC
+ NdisSend(
+ &Status,
+ Open->AdapterHandle,
+ pPacket);
+
+ if (Status != NDIS_STATUS_PENDING) {
+ // The send didn't pend so call the completion handler now
+ NPF_SendComplete(
+ Open,
+ pPacket,
+ Status
+ );
+
+ }
+
+ if(i%100==99){
+ NdisWaitEvent(&Open->WriteEvent,1000);
+ NdisResetEvent(&Open->WriteEvent);
+ }
+ }
+
+ return(STATUS_PENDING);
+
+}
+
+
+//-------------------------------------------------------------------
+
+INT
+NPF_BufferedWrite(
+ IN PIRP Irp,
+ IN PCHAR UserBuff,
+ IN ULONG UserBuffSize,
+ BOOLEAN Sync)
+{
+ POPEN_INSTANCE Open;
+ PIO_STACK_LOCATION IrpSp;
+ PNDIS_PACKET pPacket;
+ UINT i;
+ NDIS_STATUS Status;
+ LARGE_INTEGER StartTicks, CurTicks, TargetTicks;
+ LARGE_INTEGER TimeFreq;
+ struct timeval BufStartTime;
+ struct sf_pkthdr *winpcap_hdr;
+ PMDL TmpMdl;
+ PCHAR CurPos;
+ PCHAR EndOfUserBuff = UserBuff + UserBuffSize;
+
+ IF_LOUD(DbgPrint("NPF: BufferedWrite, UserBuff=%x, Size=%u\n", UserBuff, UserBuffSize);)
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ Open=IrpSp->FileObject->FsContext;
+
+ // Security check on the length of the user buffer
+ if(UserBuff==0)
+ {
+ return 0;
+ }
+
+ // Check that the MaxFrameSize is correctly initialized
+ if(Open->MaxFrameSize == 0)
+ {
+ IF_LOUD(DbgPrint("BufferedWrite: Open->MaxFrameSize not initialized, probably because of a problem in the OID query\n");)
+
+ return 0;
+ }
+
+
+ // Start from the first packet
+ winpcap_hdr = (struct sf_pkthdr*)UserBuff;
+
+ // Retrieve the time references
+ StartTicks = KeQueryPerformanceCounter(&TimeFreq);
+ BufStartTime.tv_sec = winpcap_hdr->ts.tv_sec;
+ BufStartTime.tv_usec = winpcap_hdr->ts.tv_usec;
+
+ // Chech the consistency of the user buffer
+ if( (PCHAR)winpcap_hdr + winpcap_hdr->caplen + sizeof(struct sf_pkthdr) > EndOfUserBuff )
+ {
+ IF_LOUD(DbgPrint("Buffered Write: bogus packet buffer\n");)
+
+ return -1;
+ }
+
+ // Save the current time stamp counter
+ CurTicks = KeQueryPerformanceCounter(NULL);
+
+ // Main loop: send the buffer to the wire
+ while( TRUE ){
+
+ if(winpcap_hdr->caplen ==0 || winpcap_hdr->caplen > Open->MaxFrameSize)
+ {
+ // Malformed header
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: malformed or bogus user buffer, aborting write.\n");)
+
+ return -1;
+ }
+
+ // Allocate an MDL to map the packet data
+ TmpMdl=IoAllocateMdl((PCHAR)winpcap_hdr + sizeof(struct sf_pkthdr),
+ winpcap_hdr->caplen,
+ FALSE,
+ FALSE,
+ NULL);
+
+ if (TmpMdl == NULL)
+ {
+ // Unable to map the memory: packet lost
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: unable to allocate the MDL.\n");)
+
+ return -1;
+ }
+
+ MmBuildMdlForNonPagedPool(TmpMdl); // XXX can this line be removed?
+
+ // Allocate a packet from our free list
+ NdisAllocatePacket( &Status, &pPacket, Open->PacketPool);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ // No free packets
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: no more free packets, returning.\n");)
+
+ return (PCHAR)winpcap_hdr - UserBuff;
+ }
+
+ // The packet has a buffer that needs to be freed after every single write
+ RESERVED(pPacket)->FreeBufAfterWrite = TRUE;
+
+ // Attach the MDL to the packet
+ NdisChainBufferAtFront(pPacket,TmpMdl);
+
+ // Call the MAC
+ NdisSend( &Status, Open->AdapterHandle, pPacket);
+
+ if (Status != NDIS_STATUS_PENDING) {
+ // The send didn't pend so call the completion handler now
+ NPF_SendComplete(
+ Open,
+ pPacket,
+ Status
+ );
+ }
+
+ // Step to the next packet in the buffer
+ (PCHAR)winpcap_hdr += winpcap_hdr->caplen + sizeof(struct sf_pkthdr);
+
+ // Check if the end of the user buffer has been reached
+ if( (PCHAR)winpcap_hdr >= EndOfUserBuff )
+ {
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: End of buffer.\n");)
+
+ return (PCHAR)winpcap_hdr - UserBuff;
+ }
+
+ if( Sync ){
+
+ // Release the application if it has been blocked for approximately more than 1 seconds
+ if( winpcap_hdr->ts.tv_sec - BufStartTime.tv_sec > 1 )
+ {
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: timestamp elapsed, returning.\n");)
+
+ return (PCHAR)winpcap_hdr - UserBuff;
+ }
+
+#ifndef __GNUC__
+ // Calculate the time interval to wait before sending the next packet
+ TargetTicks.QuadPart = StartTicks.QuadPart +
+ (LONGLONG)((winpcap_hdr->ts.tv_sec - BufStartTime.tv_sec) * 1000000 +
+ winpcap_hdr->ts.tv_usec - BufStartTime.tv_usec) *
+ (TimeFreq.QuadPart) / 1000000;
+
+ // Wait until the time interval has elapsed
+ while( CurTicks.QuadPart <= TargetTicks.QuadPart )
+ CurTicks = KeQueryPerformanceCounter(NULL);
+#else
+#endif
+ }
+
+ }
+
+ return (PCHAR)winpcap_hdr - UserBuff;
+
+}
+
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_SendComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_PACKET pPacket,
+ IN NDIS_STATUS Status
+ )
+
+{
+ PIRP Irp;
+ PIO_STACK_LOCATION irpSp;
+ POPEN_INSTANCE Open;
+ PMDL TmpMdl;
+
+ IF_LOUD(DbgPrint("NPF: SendComplete, BindingContext=%d\n",ProtocolBindingContext);)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+ if( RESERVED(pPacket)->FreeBufAfterWrite ){
+ // Free the MDL associated with the packet
+ NdisUnchainBufferAtFront(pPacket, &TmpMdl);
+ IoFreeMdl(TmpMdl);
+ }
+ else{
+ if((Open->Nwrites - Open->Multiple_Write_Counter) %100 == 99)
+ NdisSetEvent(&Open->WriteEvent);
+
+ Open->Multiple_Write_Counter--;
+ }
+
+ // recyle the packet
+ NdisReinitializePacket(pPacket);
+
+ // Put the packet back on the free list
+ NdisFreePacket(pPacket);
+
+ if( !(RESERVED(pPacket)->FreeBufAfterWrite) ){
+ if(Open->Multiple_Write_Counter==0){
+ // Release the buffer and awake the application
+ NdisUnchainBufferAtFront(pPacket, &TmpMdl);
+
+ Irp=RESERVED(pPacket)->Irp;
+ irpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = irpSp->Parameters.Write.Length;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ }
+ }
+
+ return;
+}
+
+
+#ifdef __GNUC__
+/*
+__divdi3()
+{
+ //_alldiv();
+}
+
+//_allmul();
+//_allrem();
+
+*/
+#endif
--- /dev/null
+#ifndef _LINUX_TYPES_H
+#define _LINUX_TYPES_H
+
+#include <ddk/ntddk.h>
+
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+typedef struct page {
+ int x;
+} mem_map_t;
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* i386 */
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+#define BITS_PER_LONG 32
+
+/* DMA addresses come in generic and 64-bit flavours. */
+
+#ifdef CONFIG_HIGHMEM64G
+typedef u64 dma_addr_t;
+#else
+typedef u32 dma_addr_t;
+#endif
+typedef u64 dma64_addr_t;
+
+
+
+/*
+ * This allows for 1024 file descriptors: if NR_OPEN is ever grown
+ * beyond that you'll have to change this too. But 1024 fd's seem to be
+ * enough even for such "real" unices like OSF/1, so hopefully this is
+ * one limit that doesn't have to be changed [again].
+ *
+ * Note that POSIX wants the FD_CLEAR(fd,fdsetp) defines to be in
+ * <sys/time.h> (and thus <linux/time.h>) - but this is a more logical
+ * place for them. Solved by having dummy defines in <sys/time.h>.
+ */
+
+/*
+ * Those macros may have been defined in <gnu/types.h>. But we always
+ * use the ones here.
+ */
+#undef __NFDBITS
+#define __NFDBITS (8 * sizeof(unsigned long))
+
+#undef __FD_SETSIZE
+#define __FD_SETSIZE 1024
+
+#undef __FDSET_LONGS
+#define __FDSET_LONGS (__FD_SETSIZE/__NFDBITS)
+
+#undef __FDELT
+#define __FDELT(d) ((d) / __NFDBITS)
+
+#undef __FDMASK
+#define __FDMASK(d) (1UL << ((d) % __NFDBITS))
+
+typedef struct {
+ unsigned long fds_bits [__FDSET_LONGS];
+} __kernel_fd_set;
+
+/* Type of a signal handler. */
+typedef void (*__kernel_sighandler_t)(int);
+
+/* Type of a SYSV IPC key. */
+typedef int __kernel_key_t;
+
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc. Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned short __kernel_dev_t;
+typedef unsigned long __kernel_ino_t;
+typedef unsigned short __kernel_mode_t;
+typedef unsigned short __kernel_nlink_t;
+typedef long __kernel_off_t;
+typedef int __kernel_pid_t;
+typedef unsigned short __kernel_ipc_pid_t;
+typedef unsigned short __kernel_uid_t;
+typedef unsigned short __kernel_gid_t;
+typedef unsigned int __kernel_size_t;
+typedef int __kernel_ssize_t;
+typedef int __kernel_ptrdiff_t;
+typedef long __kernel_time_t;
+typedef long __kernel_suseconds_t;
+typedef long __kernel_clock_t;
+typedef int __kernel_daddr_t;
+typedef char * __kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int __kernel_uid32_t;
+typedef unsigned int __kernel_gid32_t;
+
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+
+#ifdef __GNUC__
+typedef long long __kernel_loff_t;
+#endif
+
+typedef struct {
+#if defined(__KERNEL__) || defined(__USE_ALL)
+ int val[2];
+#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+ int __val[2];
+#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+} __kernel_fsid_t;
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#undef __FD_SET
+#define __FD_SET(fd,fdsetp) \
+ __asm__ __volatile__("btsl %1,%0": \
+ "=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
+
+#undef __FD_CLR
+#define __FD_CLR(fd,fdsetp) \
+ __asm__ __volatile__("btrl %1,%0": \
+ "=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
+
+#undef __FD_ISSET
+#define __FD_ISSET(fd,fdsetp) (__extension__ ({ \
+ unsigned char __result; \
+ __asm__ __volatile__("btl %1,%2 ; setb %0" \
+ :"=q" (__result) :"r" ((int) (fd)), \
+ "m" (*(__kernel_fd_set *) (fdsetp))); \
+ __result; }))
+
+#undef __FD_ZERO
+#define __FD_ZERO(fdsetp) \
+do { \
+ int __d0, __d1; \
+ __asm__ __volatile__("cld ; rep ; stosl" \
+ :"=m" (*(__kernel_fd_set *) (fdsetp)), \
+ "=&c" (__d0), "=&D" (__d1) \
+ :"a" (0), "1" (__FDSET_LONGS), \
+ "2" ((__kernel_fd_set *) (fdsetp)) : "memory"); \
+} while (0)
+
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+
+
+#ifndef __KERNEL_STRICT_NAMES
+
+typedef __kernel_fd_set fd_set;
+typedef __kernel_dev_t dev_t;
+typedef __kernel_ino_t ino_t;
+typedef __kernel_mode_t mode_t;
+typedef __kernel_nlink_t nlink_t;
+typedef __kernel_off_t off_t;
+typedef __kernel_pid_t pid_t;
+typedef __kernel_daddr_t daddr_t;
+typedef __kernel_key_t key_t;
+typedef __kernel_suseconds_t suseconds_t;
+
+#ifdef __KERNEL__
+typedef __kernel_uid32_t uid_t;
+typedef __kernel_gid32_t gid_t;
+typedef __kernel_uid16_t uid16_t;
+typedef __kernel_gid16_t gid16_t;
+
+#ifdef CONFIG_UID16
+/* This is defined by include/asm-{arch}/posix_types.h */
+typedef __kernel_old_uid_t old_uid_t;
+typedef __kernel_old_gid_t old_gid_t;
+#endif /* CONFIG_UID16 */
+
+/* libc5 includes this file to define uid_t, thus uid_t can never change
+ * when it is included by non-kernel code
+ */
+#else
+typedef __kernel_uid_t uid_t;
+typedef __kernel_gid_t gid_t;
+#endif /* __KERNEL__ */
+
+#if defined(__GNUC__)
+typedef __kernel_loff_t loff_t;
+#endif
+
+/*
+ * The following typedefs are also protected by individual ifdefs for
+ * historical reasons:
+ */
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef __kernel_size_t size_t;
+#endif
+
+#ifndef _SSIZE_T
+#define _SSIZE_T
+typedef __kernel_ssize_t ssize_t;
+#endif
+
+#ifndef _PTRDIFF_T
+#define _PTRDIFF_T
+typedef __kernel_ptrdiff_t ptrdiff_t;
+#endif
+
+#ifndef _TIME_T
+#define _TIME_T
+typedef __kernel_time_t time_t;
+#endif
+
+#ifndef _CLOCK_T
+#define _CLOCK_T
+typedef __kernel_clock_t clock_t;
+#endif
+
+#ifndef _CADDR_T
+#define _CADDR_T
+typedef __kernel_caddr_t caddr_t;
+#endif
+
+/* bsd */
+typedef unsigned char u_char;
+typedef unsigned short u_short;
+typedef unsigned int u_int;
+typedef unsigned long u_long;
+
+/* sysv */
+typedef unsigned char unchar;
+typedef unsigned short ushort;
+typedef unsigned int uint;
+typedef unsigned long ulong;
+
+#ifndef __BIT_TYPES_DEFINED__
+#define __BIT_TYPES_DEFINED__
+
+typedef __u8 u_int8_t;
+typedef __s8 int8_t;
+typedef __u16 u_int16_t;
+typedef __s16 int16_t;
+typedef __u32 u_int32_t;
+typedef __s32 int32_t;
+
+#endif /* !(__BIT_TYPES_DEFINED__) */
+
+typedef __u8 uint8_t;
+typedef __u16 uint16_t;
+typedef __u32 uint32_t;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __u64 uint64_t;
+typedef __u64 u_int64_t;
+typedef __s64 int64_t;
+#endif
+
+#endif /* __KERNEL_STRICT_NAMES */
+
+/*
+ * Below are truly Linux-specific types that should never collide with
+ * any application/library that wants linux/types.h.
+ */
+
+struct ustat {
+ __kernel_daddr_t f_tfree;
+ __kernel_ino_t f_tinode;
+ char f_fname[6];
+ char f_fpack[6];
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#ifndef __LITTLE_ENDIAN
+#define __LITTLE_ENDIAN 1234
+#endif
+#ifndef __LITTLE_ENDIAN_BITFIELD
+#define __LITTLE_ENDIAN_BITFIELD
+#endif
+
+#if 1 /* swab */
+
+/*
+ * linux/byteorder/swab.h
+ * Byte-swapping, independently from CPU endianness
+ * swabXX[ps]?(foo)
+ *
+ * Francois-Rene Rideau <fare@tunes.org> 19971205
+ * separated swab functions from cpu_to_XX,
+ * to clean up support for bizarre-endian architectures.
+ *
+ * See asm-i386/byteorder.h and suches for examples of how to provide
+ * architecture-dependent optimized versions
+ *
+ */
+
+/* casts are necessary for constants, because we never know how for sure
+ * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way.
+ */
+#define ___swab16(x) \
+({ \
+ __u16 __x = (x); \
+ ((__u16)( \
+ (((__u16)(__x) & (__u16)0x00ffU) << 8) | \
+ (((__u16)(__x) & (__u16)0xff00U) >> 8) )); \
+})
+
+#define ___swab24(x) \
+({ \
+ __u32 __x = (x); \
+ ((__u32)( \
+ ((__x & (__u32)0x000000ffUL) << 16) | \
+ (__x & (__u32)0x0000ff00UL) | \
+ ((__x & (__u32)0x00ff0000UL) >> 16) )); \
+})
+
+#define ___swab32(x) \
+({ \
+ __u32 __x = (x); \
+ ((__u32)( \
+ (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \
+ (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | \
+ (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | \
+ (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \
+})
+
+#define ___swab64(x) \
+({ \
+ __u64 __x = (x); \
+ ((__u64)( \
+ (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \
+ (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \
+ (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \
+ (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | \
+ (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | \
+ (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
+ (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \
+ (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \
+})
+
+#define ___constant_swab16(x) \
+ ((__u16)( \
+ (((__u16)(x) & (__u16)0x00ffU) << 8) | \
+ (((__u16)(x) & (__u16)0xff00U) >> 8) ))
+#define ___constant_swab24(x) \
+ ((__u32)( \
+ (((__u32)(x) & (__u32)0x000000ffU) << 16) | \
+ (((__u32)(x) & (__u32)0x0000ff00U) | \
+ (((__u32)(x) & (__u32)0x00ff0000U) >> 16) ))
+#define ___constant_swab32(x) \
+ ((__u32)( \
+ (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \
+ (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \
+ (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \
+ (((__u32)(x) & (__u32)0xff000000UL) >> 24) ))
+#define ___constant_swab64(x) \
+ ((__u64)( \
+ (__u64)(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \
+ (__u64)(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \
+ (__u64)(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \
+ (__u64)(((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \
+ (__u64)(((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \
+ (__u64)(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
+ (__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \
+ (__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) ))
+
+/*
+ * provide defaults when no architecture-specific optimization is detected
+ */
+#ifndef __arch__swab16
+# define __arch__swab16(x) ({ __u16 __tmp = (x) ; ___swab16(__tmp); })
+#endif
+#ifndef __arch__swab24
+# define __arch__swab24(x) ({ __u32 __tmp = (x) ; ___swab24(__tmp); })
+#endif
+#ifndef __arch__swab32
+# define __arch__swab32(x) ({ __u32 __tmp = (x) ; ___swab32(__tmp); })
+#endif
+#ifndef __arch__swab64
+# define __arch__swab64(x) ({ __u64 __tmp = (x) ; ___swab64(__tmp); })
+#endif
+
+#ifndef __arch__swab16p
+# define __arch__swab16p(x) __arch__swab16(*(x))
+#endif
+#ifndef __arch__swab24p
+# define __arch__swab24p(x) __arch__swab24(*(x))
+#endif
+#ifndef __arch__swab32p
+# define __arch__swab32p(x) __arch__swab32(*(x))
+#endif
+#ifndef __arch__swab64p
+# define __arch__swab64p(x) __arch__swab64(*(x))
+#endif
+
+#ifndef __arch__swab16s
+# define __arch__swab16s(x) do { *(x) = __arch__swab16p((x)); } while (0)
+#endif
+#ifndef __arch__swab24s
+# define __arch__swab24s(x) do { *(x) = __arch__swab24p((x)); } while (0)
+#endif
+#ifndef __arch__swab32s
+# define __arch__swab32s(x) do { *(x) = __arch__swab32p((x)); } while (0)
+#endif
+#ifndef __arch__swab64s
+# define __arch__swab64s(x) do { *(x) = __arch__swab64p((x)); } while (0)
+#endif
+
+
+/*
+ * Allow constant folding
+ */
+#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__)
+# define __swab16(x) \
+(__builtin_constant_p((__u16)(x)) ? \
+ ___swab16((x)) : \
+ __fswab16((x)))
+# define __swab24(x) \
+(__builtin_constant_p((__u32)(x)) ? \
+ ___swab24((x)) : \
+ __fswab24((x)))
+# define __swab32(x) \
+(__builtin_constant_p((__u32)(x)) ? \
+ ___swab32((x)) : \
+ __fswab32((x)))
+# define __swab64(x) \
+(__builtin_constant_p((__u64)(x)) ? \
+ ___swab64((x)) : \
+ __fswab64((x)))
+#else
+# define __swab16(x) __fswab16(x)
+# define __swab24(x) __fswab24(x)
+# define __swab32(x) __fswab32(x)
+# define __swab64(x) __fswab64(x)
+#endif /* OPTIMIZE */
+
+
+static __inline__ __const__ __u16 __fswab16(__u16 x)
+{
+ return __arch__swab16(x);
+}
+static __inline__ __u16 __swab16p(__u16 *x)
+{
+ return __arch__swab16p(x);
+}
+static __inline__ void __swab16s(__u16 *addr)
+{
+ __arch__swab16s(addr);
+}
+
+static __inline__ __const__ __u32 __fswab24(__u32 x)
+{
+ return __arch__swab24(x);
+}
+static __inline__ __u32 __swab24p(__u32 *x)
+{
+ return __arch__swab24p(x);
+}
+static __inline__ void __swab24s(__u32 *addr)
+{
+ __arch__swab24s(addr);
+}
+
+static __inline__ __const__ __u32 __fswab32(__u32 x)
+{
+ return __arch__swab32(x);
+}
+static __inline__ __u32 __swab32p(__u32 *x)
+{
+ return __arch__swab32p(x);
+}
+static __inline__ void __swab32s(__u32 *addr)
+{
+ __arch__swab32s(addr);
+}
+
+#ifdef __BYTEORDER_HAS_U64__
+static __inline__ __const__ __u64 __fswab64(__u64 x)
+{
+# ifdef __SWAB_64_THRU_32__
+ __u32 h = x >> 32;
+ __u32 l = x & ((1ULL<<32)-1);
+ return (((__u64)__swab32(l)) << 32) | ((__u64)(__swab32(h)));
+# else
+ return __arch__swab64(x);
+# endif
+}
+static __inline__ __u64 __swab64p(__u64 *x)
+{
+ return __arch__swab64p(x);
+}
+static __inline__ void __swab64s(__u64 *addr)
+{
+ __arch__swab64s(addr);
+}
+#endif /* __BYTEORDER_HAS_U64__ */
+
+#if defined(__KERNEL__)
+#define swab16 __swab16
+#define swab24 __swab24
+#define swab32 __swab32
+#define swab64 __swab64
+#define swab16p __swab16p
+#define swab24p __swab24p
+#define swab32p __swab32p
+#define swab64p __swab64p
+#define swab16s __swab16s
+#define swab24s __swab24s
+#define swab32s __swab32s
+#define swab64s __swab64s
+#endif
+
+#endif /* swab */
+
+
+
+#if 1 /* generic */
+
+/*
+ * linux/byteorder_generic.h
+ * Generic Byte-reordering support
+ *
+ * Francois-Rene Rideau <fare@tunes.org> 19970707
+ * gathered all the good ideas from all asm-foo/byteorder.h into one file,
+ * cleaned them up.
+ * I hope it is compliant with non-GCC compilers.
+ * I decided to put __BYTEORDER_HAS_U64__ in byteorder.h,
+ * because I wasn't sure it would be ok to put it in types.h
+ * Upgraded it to 2.1.43
+ * Francois-Rene Rideau <fare@tunes.org> 19971012
+ * Upgraded it to 2.1.57
+ * to please Linus T., replaced huge #ifdef's between little/big endian
+ * by nestedly #include'd files.
+ * Francois-Rene Rideau <fare@tunes.org> 19971205
+ * Made it to 2.1.71; now a facelift:
+ * Put files under include/linux/byteorder/
+ * Split swab from generic support.
+ *
+ * TODO:
+ * = Regular kernel maintainers could also replace all these manual
+ * byteswap macros that remain, disseminated among drivers,
+ * after some grep or the sources...
+ * = Linus might want to rename all these macros and files to fit his taste,
+ * to fit his personal naming scheme.
+ * = it seems that a few drivers would also appreciate
+ * nybble swapping support...
+ * = every architecture could add their byteswap macro in asm/byteorder.h
+ * see how some architectures already do (i386, alpha, ppc, etc)
+ * = cpu_to_beXX and beXX_to_cpu might some day need to be well
+ * distinguished throughout the kernel. This is not the case currently,
+ * since little endian, big endian, and pdp endian machines needn't it.
+ * But this might be the case for, say, a port of Linux to 20/21 bit
+ * architectures (and F21 Linux addict around?).
+ */
+
+/*
+ * The following macros are to be defined by <asm/byteorder.h>:
+ *
+ * Conversion of long and short int between network and host format
+ * ntohl(__u32 x)
+ * ntohs(__u16 x)
+ * htonl(__u32 x)
+ * htons(__u16 x)
+ * It seems that some programs (which? where? or perhaps a standard? POSIX?)
+ * might like the above to be functions, not macros (why?).
+ * if that's true, then detect them, and take measures.
+ * Anyway, the measure is: define only ___ntohl as a macro instead,
+ * and in a separate file, have
+ * unsigned long inline ntohl(x){return ___ntohl(x);}
+ *
+ * The same for constant arguments
+ * __constant_ntohl(__u32 x)
+ * __constant_ntohs(__u16 x)
+ * __constant_htonl(__u32 x)
+ * __constant_htons(__u16 x)
+ *
+ * Conversion of XX-bit integers (16- 32- or 64-)
+ * between native CPU format and little/big endian format
+ * 64-bit stuff only defined for proper architectures
+ * cpu_to_[bl]eXX(__uXX x)
+ * [bl]eXX_to_cpu(__uXX x)
+ *
+ * The same, but takes a pointer to the value to convert
+ * cpu_to_[bl]eXXp(__uXX x)
+ * [bl]eXX_to_cpup(__uXX x)
+ *
+ * The same, but change in situ
+ * cpu_to_[bl]eXXs(__uXX x)
+ * [bl]eXX_to_cpus(__uXX x)
+ *
+ * See asm-foo/byteorder.h for examples of how to provide
+ * architecture-optimized versions
+ *
+ */
+
+
+#if defined(__KERNEL__)
+/*
+ * inside the kernel, we can use nicknames;
+ * outside of it, we must avoid POSIX namespace pollution...
+ */
+#define cpu_to_le64 __cpu_to_le64
+#define le64_to_cpu __le64_to_cpu
+#define cpu_to_le32 __cpu_to_le32
+#define le32_to_cpu __le32_to_cpu
+#define cpu_to_le16 __cpu_to_le16
+#define le16_to_cpu __le16_to_cpu
+#define cpu_to_be64 __cpu_to_be64
+#define be64_to_cpu __be64_to_cpu
+#define cpu_to_be32 __cpu_to_be32
+#define be32_to_cpu __be32_to_cpu
+#define cpu_to_be16 __cpu_to_be16
+#define be16_to_cpu __be16_to_cpu
+#define cpu_to_le64p __cpu_to_le64p
+#define le64_to_cpup __le64_to_cpup
+#define cpu_to_le32p __cpu_to_le32p
+#define le32_to_cpup __le32_to_cpup
+#define cpu_to_le16p __cpu_to_le16p
+#define le16_to_cpup __le16_to_cpup
+#define cpu_to_be64p __cpu_to_be64p
+#define be64_to_cpup __be64_to_cpup
+#define cpu_to_be32p __cpu_to_be32p
+#define be32_to_cpup __be32_to_cpup
+#define cpu_to_be16p __cpu_to_be16p
+#define be16_to_cpup __be16_to_cpup
+#define cpu_to_le64s __cpu_to_le64s
+#define le64_to_cpus __le64_to_cpus
+#define cpu_to_le32s __cpu_to_le32s
+#define le32_to_cpus __le32_to_cpus
+#define cpu_to_le16s __cpu_to_le16s
+#define le16_to_cpus __le16_to_cpus
+#define cpu_to_be64s __cpu_to_be64s
+#define be64_to_cpus __be64_to_cpus
+#define cpu_to_be32s __cpu_to_be32s
+#define be32_to_cpus __be32_to_cpus
+#define cpu_to_be16s __cpu_to_be16s
+#define be16_to_cpus __be16_to_cpus
+#endif
+
+
+/*
+ * Handle ntohl and suches. These have various compatibility
+ * issues - like we want to give the prototype even though we
+ * also have a macro for them in case some strange program
+ * wants to take the address of the thing or something..
+ *
+ * Note that these used to return a "long" in libc5, even though
+ * long is often 64-bit these days.. Thus the casts.
+ *
+ * They have to be macros in order to do the constant folding
+ * correctly - if the argument passed into a inline function
+ * it is no longer constant according to gcc..
+ */
+
+#undef ntohl
+#undef ntohs
+#undef htonl
+#undef htons
+
+/*
+ * Do the prototypes. Somebody might want to take the
+ * address or some such sick thing..
+ */
+#if defined(__KERNEL__) || (defined (__GLIBC__) && __GLIBC__ >= 2)
+extern __u32 ntohl(__u32);
+extern __u32 htonl(__u32);
+#else
+extern unsigned long int ntohl(unsigned long int);
+extern unsigned long int htonl(unsigned long int);
+#endif
+extern unsigned short int ntohs(unsigned short int);
+extern unsigned short int htons(unsigned short int);
+
+
+#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__) && !defined(__STRICT_ANSI__)
+
+#define ___htonl(x) __cpu_to_be32(x)
+#define ___htons(x) __cpu_to_be16(x)
+#define ___ntohl(x) __be32_to_cpu(x)
+#define ___ntohs(x) __be16_to_cpu(x)
+
+#if defined(__KERNEL__) || (defined (__GLIBC__) && __GLIBC__ >= 2)
+#define htonl(x) ___htonl(x)
+#define ntohl(x) ___ntohl(x)
+#else
+#define htonl(x) ((unsigned long)___htonl(x))
+#define ntohl(x) ((unsigned long)___ntohl(x))
+#endif
+#define htons(x) ___htons(x)
+#define ntohs(x) ___ntohs(x)
+
+#endif /* OPTIMIZE */
+
+#endif /* generic */
+
+
+#define __constant_htonl(x) ___constant_swab32((x))
+#define __constant_ntohl(x) ___constant_swab32((x))
+#define __constant_htons(x) ___constant_swab16((x))
+#define __constant_ntohs(x) ___constant_swab16((x))
+#define __constant_cpu_to_le64(x) ((__u64)(x))
+#define __constant_le64_to_cpu(x) ((__u64)(x))
+#define __constant_cpu_to_le32(x) ((__u32)(x))
+#define __constant_le32_to_cpu(x) ((__u32)(x))
+#define __constant_cpu_to_le24(x) ((__u32)(x))
+#define __constant_le24_to_cpu(x) ((__u32)(x))
+#define __constant_cpu_to_le16(x) ((__u16)(x))
+#define __constant_le16_to_cpu(x) ((__u16)(x))
+#define __constant_cpu_to_be64(x) ___constant_swab64((x))
+#define __constant_be64_to_cpu(x) ___constant_swab64((x))
+#define __constant_cpu_to_be32(x) ___constant_swab32((x))
+#define __constant_be32_to_cpu(x) ___constant_swab32((x))
+#define __constant_cpu_to_be24(x) ___constant_swab24((x))
+#define __constant_be24_to_cpu(x) ___constant_swab24((x))
+#define __constant_cpu_to_be16(x) ___constant_swab16((x))
+#define __constant_be16_to_cpu(x) ___constant_swab16((x))
+#define __cpu_to_le64(x) ((__u64)(x))
+#define __le64_to_cpu(x) ((__u64)(x))
+#define __cpu_to_le32(x) ((__u32)(x))
+#define __le32_to_cpu(x) ((__u32)(x))
+#define __cpu_to_le24(x) ((__u32)(x))
+#define __le24_to_cpu(x) ((__u32)(x))
+#define __cpu_to_le16(x) ((__u16)(x))
+#define __le16_to_cpu(x) ((__u16)(x))
+#define __cpu_to_be64(x) __swab64((x))
+#define __be64_to_cpu(x) __swab64((x))
+#define __cpu_to_be32(x) __swab32((x))
+#define __be32_to_cpu(x) __swab32((x))
+#define __cpu_to_be24(x) __swab24((x))
+#define __be24_to_cpu(x) __swab24((x))
+#define __cpu_to_be16(x) __swab16((x))
+#define __be16_to_cpu(x) __swab16((x))
+#define __cpu_to_le64p(x) (*(__u64*)(x))
+#define __le64_to_cpup(x) (*(__u64*)(x))
+#define __cpu_to_le32p(x) (*(__u32*)(x))
+#define __le32_to_cpup(x) (*(__u32*)(x))
+#define __cpu_to_le24p(x) (*(__u32*)(x))
+#define __le24_to_cpup(x) (*(__u32*)(x))
+#define __cpu_to_le16p(x) (*(__u16*)(x))
+#define __le16_to_cpup(x) (*(__u16*)(x))
+#define __cpu_to_be64p(x) __swab64p((x))
+#define __be64_to_cpup(x) __swab64p((x))
+#define __cpu_to_be32p(x) __swab32p((x))
+#define __be32_to_cpup(x) __swab32p((x))
+#define __cpu_to_be24p(x) __swab24p((x))
+#define __be24_to_cpup(x) __swab24p((x))
+#define __cpu_to_be16p(x) __swab16p((x))
+#define __be16_to_cpup(x) __swab16p((x))
+#define __cpu_to_le64s(x) do {} while (0)
+#define __le64_to_cpus(x) do {} while (0)
+#define __cpu_to_le32s(x) do {} while (0)
+#define __le32_to_cpus(x) do {} while (0)
+#define __cpu_to_le24s(x) do {} while (0)
+#define __le24_to_cpus(x) do {} while (0)
+#define __cpu_to_le16s(x) do {} while (0)
+#define __le16_to_cpus(x) do {} while (0)
+#define __cpu_to_be64s(x) __swab64s((x))
+#define __be64_to_cpus(x) __swab64s((x))
+#define __cpu_to_be32s(x) __swab32s((x))
+#define __be32_to_cpus(x) __swab32s((x))
+#define __cpu_to_be24s(x) __swab24s((x))
+#define __be24_to_cpus(x) __swab24s((x))
+#define __cpu_to_be16s(x) __swab16s((x))
+#define __be16_to_cpus(x) __swab16s((x))
+
+
+
+
+
+
+
+
+#if 1
+
+/* Dummy types */
+
+#define ____cacheline_aligned
+
+typedef struct
+{
+ volatile unsigned int lock;
+} rwlock_t;
+
+typedef struct {
+ volatile unsigned int lock;
+} spinlock_t;
+
+struct task_struct;
+
+
+
+
+
+#if 1 /* atomic */
+
+/*
+ * Atomic operations that C can't guarantee us. Useful for
+ * resource counting etc..
+ */
+
+#ifdef CONFIG_SMP
+#define LOCK "lock ; "
+#else
+#define LOCK ""
+#endif
+
+/*
+ * Make sure gcc doesn't try to be clever and move things around
+ * on us. We need to use _exactly_ the address the user gave us,
+ * not some alias that contains the same information.
+ */
+typedef struct { volatile int counter; } atomic_t;
+
+#define ATOMIC_INIT(i) { (i) }
+
+/**
+ * atomic_read - read atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically reads the value of @v. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+#define atomic_read(v) ((v)->counter)
+
+/**
+ * atomic_set - set atomic variable
+ * @v: pointer of type atomic_t
+ * @i: required value
+ *
+ * Atomically sets the value of @v to @i. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+#define atomic_set(v,i) (((v)->counter) = (i))
+
+/**
+ * atomic_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+ *
+ * Atomically adds @i to @v. Note that the guaranteed useful range
+ * of an atomic_t is only 24 bits.
+ */
+static __inline__ void atomic_add(int i, atomic_t *v)
+{
+#if 0
+ __asm__ __volatile__(
+ LOCK "addl %1,%0"
+ :"=m" (v->counter)
+ :"ir" (i), "m" (v->counter));
+#endif
+}
+
+/**
+ * atomic_sub - subtract the atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+static __inline__ void atomic_sub(int i, atomic_t *v)
+{
+#if 0
+ __asm__ __volatile__(
+ LOCK "subl %1,%0"
+ :"=m" (v->counter)
+ :"ir" (i), "m" (v->counter));
+#endif
+}
+
+/**
+ * atomic_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+static __inline__ int atomic_sub_and_test(int i, atomic_t *v)
+{
+#if 0
+ unsigned char c;
+
+ __asm__ __volatile__(
+ LOCK "subl %2,%0; sete %1"
+ :"=m" (v->counter), "=qm" (c)
+ :"ir" (i), "m" (v->counter) : "memory");
+ return c;
+#endif
+}
+
+/**
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+static __inline__ void atomic_inc(atomic_t *v)
+{
+#if 0
+ __asm__ __volatile__(
+ LOCK "incl %0"
+ :"=m" (v->counter)
+ :"m" (v->counter));
+#endif
+}
+
+/**
+ * atomic_dec - decrement atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+static __inline__ void atomic_dec(atomic_t *v)
+{
+#if 0
+ __asm__ __volatile__(
+ LOCK "decl %0"
+ :"=m" (v->counter)
+ :"m" (v->counter));
+#endif
+}
+
+/**
+ * atomic_dec_and_test - decrement and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+static __inline__ int atomic_dec_and_test(atomic_t *v)
+{
+#if 0
+ unsigned char c;
+
+ __asm__ __volatile__(
+ LOCK "decl %0; sete %1"
+ :"=m" (v->counter), "=qm" (c)
+ :"m" (v->counter) : "memory");
+ return c != 0;
+#else
+ return 1;
+#endif
+}
+
+/**
+ * atomic_inc_and_test - increment and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+static __inline__ int atomic_inc_and_test(atomic_t *v)
+{
+#if 0
+ unsigned char c;
+
+ __asm__ __volatile__(
+ LOCK "incl %0; sete %1"
+ :"=m" (v->counter), "=qm" (c)
+ :"m" (v->counter) : "memory");
+ return c != 0;
+#else
+ return 1;
+#endif
+}
+
+/**
+ * atomic_add_negative - add and test if negative
+ * @v: pointer of type atomic_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero. Note that the guaranteed
+ * useful range of an atomic_t is only 24 bits.
+ */
+static __inline__ int atomic_add_negative(int i, atomic_t *v)
+{
+#if 0
+ unsigned char c;
+
+ __asm__ __volatile__(
+ LOCK "addl %2,%0; sets %1"
+ :"=m" (v->counter), "=qm" (c)
+ :"ir" (i), "m" (v->counter) : "memory");
+ return c;
+#else
+ return 0;
+#endif
+}
+
+/* These are x86-specific, used by some header files */
+#define atomic_clear_mask(mask, addr)
+#if 0
+__asm__ __volatile__(LOCK "andl %0,%1" \
+: : "r" (~(mask)),"m" (*addr) : "memory")
+#endif
+
+#define atomic_set_mask(mask, addr)
+#if 0
+__asm__ __volatile__(LOCK "orl %0,%1" \
+: : "r" (mask),"m" (*addr) : "memory")
+#endif
+
+/* Atomic operations are already serializing on x86 */
+#define smp_mb__before_atomic_dec()
+#define smp_mb__after_atomic_dec()
+#define smp_mb__before_atomic_inc()
+#define smp_mb__after_atomic_inc()
+
+
+
+#endif /* atomic */
+
+
+
+
+
+#if 1 /* list */
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+#if 0
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+#endif
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+#if 0
+ __list_add(new, head, head->next);
+#endif
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+#if 0
+ __list_add(new, head->prev, head);
+#endif
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head *prev, struct list_head *next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+#if 0
+ __list_del(entry->prev, entry->next);
+ entry->next = (void *) 0;
+ entry->prev = (void *) 0;
+#endif
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+#if 0
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+#endif
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+#if 0
+ __list_del(list->prev, list->next);
+ list_add(list, head);
+#endif
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+#if 0
+ __list_del(list->prev, list->next);
+ list_add_tail(list, head);
+#endif
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(struct list_head *head)
+{
+ return head->next == head;
+}
+
+static inline void __list_splice(struct list_head *list,
+ struct list_head *head)
+{
+#if 0
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+#endif
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+#if 0
+ if (!list_empty(list))
+ __list_splice(list, head);
+#endif
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+ struct list_head *head)
+{
+#if 0
+ if (!list_empty(list)) {
+ __list_splice(list, head);
+ INIT_LIST_HEAD(list);
+ }
+#endif
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member)
+#if 0
+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+#endif
+
+/**
+ * list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each(pos, head)
+#if 0
+ for (pos = (head)->next, prefetch(pos->next); pos != (head); \
+ pos = pos->next, prefetch(pos->next))
+#endif
+
+/**
+ * list_for_each_prev - iterate over a list backwards
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each_prev(pos, head)
+#if 0
+ for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
+ pos = pos->prev, prefetch(pos->prev))
+#endif
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop counter.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_safe(pos, n, head)
+#if 0
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+#endif
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member)
+#if 0
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ prefetch(pos->member.next); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next))
+#endif
+
+#endif /* list */
+
+
+
+
+
+#if 1 /* wait */
+
+#define WNOHANG 0x00000001
+#define WUNTRACED 0x00000002
+
+#define __WNOTHREAD 0x20000000 /* Don't wait on children of other threads in this group */
+#define __WALL 0x40000000 /* Wait on all children, regardless of type */
+#define __WCLONE 0x80000000 /* Wait only on non-SIGCHLD children */
+
+#if 0
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/stddef.h>
+#include <linux/spinlock.h>
+#include <linux/config.h>
+
+#include <asm/page.h>
+#include <asm/processor.h>
+#endif
+
+/*
+ * Debug control. Slow but useful.
+ */
+#if defined(CONFIG_DEBUG_WAITQ)
+#define WAITQUEUE_DEBUG 1
+#else
+#define WAITQUEUE_DEBUG 0
+#endif
+
+struct __wait_queue {
+ unsigned int flags;
+#define WQ_FLAG_EXCLUSIVE 0x01
+ struct task_struct * task;
+ struct list_head task_list;
+#if WAITQUEUE_DEBUG
+ long __magic;
+ long __waker;
+#endif
+};
+typedef struct __wait_queue wait_queue_t;
+
+/*
+ * 'dual' spinlock architecture. Can be switched between spinlock_t and
+ * rwlock_t locks via changing this define. Since waitqueues are quite
+ * decoupled in the new architecture, lightweight 'simple' spinlocks give
+ * us slightly better latencies and smaller waitqueue structure size.
+ */
+#define USE_RW_WAIT_QUEUE_SPINLOCK 0
+
+#if USE_RW_WAIT_QUEUE_SPINLOCK
+# define wq_lock_t rwlock_t
+# define WAITQUEUE_RW_LOCK_UNLOCKED RW_LOCK_UNLOCKED
+
+# define wq_read_lock read_lock
+# define wq_read_lock_irqsave read_lock_irqsave
+# define wq_read_unlock_irqrestore read_unlock_irqrestore
+# define wq_read_unlock read_unlock
+# define wq_write_lock_irq write_lock_irq
+# define wq_write_lock_irqsave write_lock_irqsave
+# define wq_write_unlock_irqrestore write_unlock_irqrestore
+# define wq_write_unlock write_unlock
+#else
+# define wq_lock_t spinlock_t
+# define WAITQUEUE_RW_LOCK_UNLOCKED SPIN_LOCK_UNLOCKED
+
+# define wq_read_lock spin_lock
+# define wq_read_lock_irqsave spin_lock_irqsave
+# define wq_read_unlock spin_unlock
+# define wq_read_unlock_irqrestore spin_unlock_irqrestore
+# define wq_write_lock_irq spin_lock_irq
+# define wq_write_lock_irqsave spin_lock_irqsave
+# define wq_write_unlock_irqrestore spin_unlock_irqrestore
+# define wq_write_unlock spin_unlock
+#endif
+
+struct __wait_queue_head {
+ wq_lock_t lock;
+ struct list_head task_list;
+#if WAITQUEUE_DEBUG
+ long __magic;
+ long __creator;
+#endif
+};
+typedef struct __wait_queue_head wait_queue_head_t;
+
+
+/*
+ * Debugging macros. We eschew `do { } while (0)' because gcc can generate
+ * spurious .aligns.
+ */
+#if WAITQUEUE_DEBUG
+#define WQ_BUG() BUG()
+#define CHECK_MAGIC(x)
+#if 0
+ do { \
+ if ((x) != (long)&(x)) { \
+ printk("bad magic %lx (should be %lx), ", \
+ (long)x, (long)&(x)); \
+ WQ_BUG(); \
+ } \
+ } while (0)
+#endif
+
+#define CHECK_MAGIC_WQHEAD(x)
+#if 0
+ do { \
+ if ((x)->__magic != (long)&((x)->__magic)) { \
+ printk("bad magic %lx (should be %lx, creator %lx), ", \
+ (x)->__magic, (long)&((x)->__magic), (x)->__creator); \
+ WQ_BUG(); \
+ } \
+ } while (0)
+#endif
+
+#define WQ_CHECK_LIST_HEAD(list)
+#if 0
+ do { \
+ if (!(list)->next || !(list)->prev) \
+ WQ_BUG(); \
+ } while(0)
+#endif
+
+#define WQ_NOTE_WAKER(tsk)
+#if 0
+ do { \
+ (tsk)->__waker = (long)__builtin_return_address(0); \
+ } while (0)
+#endif
+#else
+#define WQ_BUG()
+#define CHECK_MAGIC(x)
+#define CHECK_MAGIC_WQHEAD(x)
+#define WQ_CHECK_LIST_HEAD(list)
+#define WQ_NOTE_WAKER(tsk)
+#endif
+
+/*
+ * Macros for declaration and initialisaton of the datatypes
+ */
+
+#if WAITQUEUE_DEBUG
+# define __WAITQUEUE_DEBUG_INIT(name) //(long)&(name).__magic, 0
+# define __WAITQUEUE_HEAD_DEBUG_INIT(name) //(long)&(name).__magic, (long)&(name).__magic
+#else
+# define __WAITQUEUE_DEBUG_INIT(name)
+# define __WAITQUEUE_HEAD_DEBUG_INIT(name)
+#endif
+
+#define __WAITQUEUE_INITIALIZER(name, tsk)
+#if 0
+{
+ task: tsk, \
+ task_list: { NULL, NULL }, \
+ __WAITQUEUE_DEBUG_INIT(name)}
+#endif
+
+#define DECLARE_WAITQUEUE(name, tsk)
+#if 0
+ wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)
+#endif
+
+#define __WAIT_QUEUE_HEAD_INITIALIZER(name)
+#if 0
+{
+ lock: WAITQUEUE_RW_LOCK_UNLOCKED, \
+ task_list: { &(name).task_list, &(name).task_list }, \
+ __WAITQUEUE_HEAD_DEBUG_INIT(name)}
+#endif
+
+#define DECLARE_WAIT_QUEUE_HEAD(name)
+#if 0
+ wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
+#endif
+
+static inline void init_waitqueue_head(wait_queue_head_t *q)
+{
+#if 0
+#if WAITQUEUE_DEBUG
+ if (!q)
+ WQ_BUG();
+#endif
+ q->lock = WAITQUEUE_RW_LOCK_UNLOCKED;
+ INIT_LIST_HEAD(&q->task_list);
+#if WAITQUEUE_DEBUG
+ q->__magic = (long)&q->__magic;
+ q->__creator = (long)current_text_addr();
+#endif
+#endif
+}
+
+static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p)
+{
+#if 0
+#if WAITQUEUE_DEBUG
+ if (!q || !p)
+ WQ_BUG();
+#endif
+ q->flags = 0;
+ q->task = p;
+#if WAITQUEUE_DEBUG
+ q->__magic = (long)&q->__magic;
+#endif
+#endif
+}
+
+static inline int waitqueue_active(wait_queue_head_t *q)
+{
+#if 0
+#if WAITQUEUE_DEBUG
+ if (!q)
+ WQ_BUG();
+ CHECK_MAGIC_WQHEAD(q);
+#endif
+
+ return !list_empty(&q->task_list);
+#endif
+}
+
+static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
+{
+#if 0
+#if WAITQUEUE_DEBUG
+ if (!head || !new)
+ WQ_BUG();
+ CHECK_MAGIC_WQHEAD(head);
+ CHECK_MAGIC(new->__magic);
+ if (!head->task_list.next || !head->task_list.prev)
+ WQ_BUG();
+#endif
+ list_add(&new->task_list, &head->task_list);
+#endif
+}
+
+/*
+ * Used for wake-one threads:
+ */
+static inline void __add_wait_queue_tail(wait_queue_head_t *head,
+ wait_queue_t *new)
+{
+#if 0
+#if WAITQUEUE_DEBUG
+ if (!head || !new)
+ WQ_BUG();
+ CHECK_MAGIC_WQHEAD(head);
+ CHECK_MAGIC(new->__magic);
+ if (!head->task_list.next || !head->task_list.prev)
+ WQ_BUG();
+#endif
+ list_add_tail(&new->task_list, &head->task_list);
+#endif
+}
+
+static inline void __remove_wait_queue(wait_queue_head_t *head,
+ wait_queue_t *old)
+{
+#if 0
+#if WAITQUEUE_DEBUG
+ if (!old)
+ WQ_BUG();
+ CHECK_MAGIC(old->__magic);
+#endif
+ list_del(&old->task_list);
+#endif
+}
+
+
+
+
+#endif /* wait */
+
+
+#endif
+
+
+
+
+#if 1 /* slab */
+
+typedef struct
+{
+ int x;
+} kmem_cache_s;
+
+typedef struct kmem_cache_s kmem_cache_t;
+
+#if 0
+#include <linux/mm.h>
+#include <linux/cache.h>
+#endif
+
+/* flags for kmem_cache_alloc() */
+#define SLAB_NOFS GFP_NOFS
+#define SLAB_NOIO GFP_NOIO
+#define SLAB_NOHIGHIO GFP_NOHIGHIO
+#define SLAB_ATOMIC GFP_ATOMIC
+#define SLAB_USER GFP_USER
+#define SLAB_KERNEL GFP_KERNEL
+#define SLAB_NFS GFP_NFS
+#define SLAB_DMA GFP_DMA
+
+#define SLAB_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_HIGHIO|__GFP_FS)
+#define SLAB_NO_GROW 0x00001000UL /* don't grow a cache */
+
+/* flags to pass to kmem_cache_create().
+ * The first 3 are only valid when the allocator as been build
+ * SLAB_DEBUG_SUPPORT.
+ */
+#define SLAB_DEBUG_FREE 0x00000100UL /* Peform (expensive) checks on free */
+#define SLAB_DEBUG_INITIAL 0x00000200UL /* Call constructor (as verifier) */
+#define SLAB_RED_ZONE 0x00000400UL /* Red zone objs in a cache */
+#define SLAB_POISON 0x00000800UL /* Poison objects */
+#define SLAB_NO_REAP 0x00001000UL /* never reap from the cache */
+#define SLAB_HWCACHE_ALIGN 0x00002000UL /* align objs on a h/w cache lines */
+#define SLAB_CACHE_DMA 0x00004000UL /* use GFP_DMA memory */
+#define SLAB_MUST_HWCACHE_ALIGN 0x00008000UL /* force alignment */
+
+/* flags passed to a constructor func */
+#define SLAB_CTOR_CONSTRUCTOR 0x001UL /* if not set, then deconstructor */
+#define SLAB_CTOR_ATOMIC 0x002UL /* tell constructor it can't sleep */
+#define SLAB_CTOR_VERIFY 0x004UL /* tell constructor it's a verify call */
+
+/* prototypes */
+extern void kmem_cache_init(void);
+extern void kmem_cache_sizes_init(void);
+
+extern kmem_cache_t *kmem_find_general_cachep(size_t, int gfpflags);
+extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned long,
+ void (*)(void *, kmem_cache_t *, unsigned long),
+ void (*)(void *, kmem_cache_t *, unsigned long));
+extern int kmem_cache_destroy(kmem_cache_t *);
+extern int kmem_cache_shrink(kmem_cache_t *);
+extern void *kmem_cache_alloc(kmem_cache_t *, int);
+extern void kmem_cache_free(kmem_cache_t *, void *);
+extern unsigned int kmem_cache_size(kmem_cache_t *);
+
+extern void *kmalloc(size_t, int);
+extern void kfree(const void *);
+
+//extern int FASTCALL(kmem_cache_reap(int));
+
+/* System wide caches */
+extern kmem_cache_t *vm_area_cachep;
+extern kmem_cache_t *mm_cachep;
+extern kmem_cache_t *names_cachep;
+extern kmem_cache_t *files_cachep;
+extern kmem_cache_t *filp_cachep;
+extern kmem_cache_t *dquot_cachep;
+extern kmem_cache_t *bh_cachep;
+extern kmem_cache_t *fs_cachep;
+extern kmem_cache_t *sigact_cachep;
+
+#endif /* slab */
+
+
+
+/*
+ * Berkeley style UIO structures - Alan Cox 1994.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+
+/* A word of warning: Our uio structure will clash with the C library one (which is now obsolete). Remove the C
+ library one from sys/uio.h if you have a very old library set */
+
+struct iovec
+{
+ void *iov_base; /* BSD uses caddr_t (1003.1g requires void *) */
+ __kernel_size_t iov_len; /* Must be size_t (1003.1g) */
+};
+
+/*
+ * UIO_MAXIOV shall be at least 16 1003.1g (5.4.1.1)
+ */
+
+#define UIO_FASTIOV 8
+#define UIO_MAXIOV 1024
+#if 0
+#define UIO_MAXIOV 16 /* Maximum iovec's in one operation
+ 16 matches BSD */
+ /* Beg pardon: BSD has 1024 --ANK */
+#endif
+
+
+
+/*
+ * In Linux 2.4, static timers have been removed from the kernel.
+ * Timers may be dynamically created and destroyed, and should be initialized
+ * by a call to init_timer() upon creation.
+ *
+ * The "data" field enables use of a common timeout function for several
+ * timeouts. You can use this field to distinguish between the different
+ * invocations.
+ */
+struct timer_list {
+ struct list_head list;
+ unsigned long expires;
+ unsigned long data;
+ void (*function)(unsigned long);
+};
+
+
+
+struct timeval {
+ unsigned long tv_sec;
+ unsigned long tv_usec;
+// time_t tv_sec; /* seconds */
+// suseconds_t tv_usec; /* microseconds */
+};
+
+
+
+
+
+
+
+#if 1 /* poll */
+
+struct file;
+
+struct poll_table_page;
+
+typedef struct poll_table_struct {
+ int error;
+ struct poll_table_page * table;
+} poll_table;
+
+extern void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p);
+
+static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
+{
+ if (p && wait_address)
+ __pollwait(filp, wait_address, p);
+}
+
+static inline void poll_initwait(poll_table* pt)
+{
+ pt->error = 0;
+ pt->table = NULL;
+}
+extern void poll_freewait(poll_table* pt);
+
+
+/*
+ * Scaleable version of the fd_set.
+ */
+
+typedef struct {
+ unsigned long *in, *out, *ex;
+ unsigned long *res_in, *res_out, *res_ex;
+} fd_set_bits;
+
+/*
+ * How many longwords for "nr" bits?
+ */
+#define FDS_BITPERLONG (8*sizeof(long))
+#define FDS_LONGS(nr) (((nr)+FDS_BITPERLONG-1)/FDS_BITPERLONG)
+#define FDS_BYTES(nr) (FDS_LONGS(nr)*sizeof(long))
+
+/*
+ * We do a VERIFY_WRITE here even though we are only reading this time:
+ * we'll write to it eventually..
+ *
+ * Use "unsigned long" accesses to let user-mode fd_set's be long-aligned.
+ */
+static inline
+int get_fd_set(unsigned long nr, void *ufdset, unsigned long *fdset)
+{
+#if 0
+ nr = FDS_BYTES(nr);
+ if (ufdset) {
+ int error;
+ error = verify_area(VERIFY_WRITE, ufdset, nr);
+ if (!error && __copy_from_user(fdset, ufdset, nr))
+ error = -EFAULT;
+ return error;
+ }
+ memset(fdset, 0, nr);
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+static inline
+void set_fd_set(unsigned long nr, void *ufdset, unsigned long *fdset)
+{
+#if 0
+ if (ufdset)
+ __copy_to_user(ufdset, fdset, FDS_BYTES(nr));
+#endif
+}
+
+static inline
+void zero_fd_set(unsigned long nr, unsigned long *fdset)
+{
+#if 0
+ memset(fdset, 0, FDS_BYTES(nr));
+#endif
+}
+
+extern int do_select(int n, fd_set_bits *fds, long *timeout);
+
+#endif /* poll */
+
+
+
+typedef struct
+{
+ int x;
+} read_descriptor_t;
+
+
+
+
+
+#if 1 /* poll */
+
+/* These are specified by iBCS2 */
+#define POLLIN 0x0001
+#define POLLPRI 0x0002
+#define POLLOUT 0x0004
+#define POLLERR 0x0008
+#define POLLHUP 0x0010
+#define POLLNVAL 0x0020
+
+/* The rest seem to be more-or-less nonstandard. Check them! */
+#define POLLRDNORM 0x0040
+#define POLLRDBAND 0x0080
+#define POLLWRNORM 0x0100
+#define POLLWRBAND 0x0200
+#define POLLMSG 0x0400
+
+struct pollfd {
+ int fd;
+ short events;
+ short revents;
+};
+
+#endif /* poll */
+
+#endif /* _LINUX_TYPES_H */
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS TCP/IP protocol driver
+ * FILE: include/tcpcore.h
+ * PURPOSE: Transmission Control Protocol definitions
+ * REVISIONS:
+ * CSH 01/01-2003 Ported from linux kernel 2.4.20
+ */
+
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the TCP module.
+ *
+ * Version: @(#)tcp.h 1.0.5 05/23/93
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef __TCPCORE_H
+#define __TCPCORE_H
+
+#include "tcpdef.h"
+
+
+struct socket;
+
+
+
+#if 1 /* skbuff */
+
+#define HAVE_ALLOC_SKB /* For the drivers to know */
+#define HAVE_ALIGNABLE_SKB /* Ditto 8) */
+#define SLAB_SKB /* Slabified skbuffs */
+
+#define CHECKSUM_NONE 0
+#define CHECKSUM_HW 1
+#define CHECKSUM_UNNECESSARY 2
+
+#define SKB_DATA_ALIGN(X) (((X) + (SMP_CACHE_BYTES-1)) & ~(SMP_CACHE_BYTES-1))
+#define SKB_MAX_ORDER(X,ORDER) (((PAGE_SIZE<<(ORDER)) - (X) - sizeof(struct skb_shared_info))&~(SMP_CACHE_BYTES-1))
+#define SKB_MAX_HEAD(X) (SKB_MAX_ORDER((X),0))
+#define SKB_MAX_ALLOC (SKB_MAX_ORDER(0,2))
+
+/* A. Checksumming of received packets by device.
+ *
+ * NONE: device failed to checksum this packet.
+ * skb->csum is undefined.
+ *
+ * UNNECESSARY: device parsed packet and wouldbe verified checksum.
+ * skb->csum is undefined.
+ * It is bad option, but, unfortunately, many of vendors do this.
+ * Apparently with secret goal to sell you new device, when you
+ * will add new protocol to your host. F.e. IPv6. 8)
+ *
+ * HW: the most generic way. Device supplied checksum of _all_
+ * the packet as seen by netif_rx in skb->csum.
+ * NOTE: Even if device supports only some protocols, but
+ * is able to produce some skb->csum, it MUST use HW,
+ * not UNNECESSARY.
+ *
+ * B. Checksumming on output.
+ *
+ * NONE: skb is checksummed by protocol or csum is not required.
+ *
+ * HW: device is required to csum packet as seen by hard_start_xmit
+ * from skb->h.raw to the end and to record the checksum
+ * at skb->h.raw+skb->csum.
+ *
+ * Device must show its capabilities in dev->features, set
+ * at device setup time.
+ * NETIF_F_HW_CSUM - it is clever device, it is able to checksum
+ * everything.
+ * NETIF_F_NO_CSUM - loopback or reliable single hop media.
+ * NETIF_F_IP_CSUM - device is dumb. It is able to csum only
+ * TCP/UDP over IPv4. Sigh. Vendors like this
+ * way by an unknown reason. Though, see comment above
+ * about CHECKSUM_UNNECESSARY. 8)
+ *
+ * Any questions? No questions, good. --ANK
+ */
+
+#ifdef __i386__
+#define NET_CALLER(arg) (*(((void**)&arg)-1))
+#else
+#define NET_CALLER(arg) __builtin_return_address(0)
+#endif
+
+#ifdef CONFIG_NETFILTER
+struct nf_conntrack {
+ atomic_t use;
+ void (*destroy)(struct nf_conntrack *);
+};
+
+struct nf_ct_info {
+ struct nf_conntrack *master;
+};
+#endif
+
+struct sk_buff_head {
+ /* These two members must be first. */
+ struct sk_buff * next;
+ struct sk_buff * prev;
+
+ __u32 qlen;
+ spinlock_t lock;
+};
+
+struct sk_buff;
+
+#define MAX_SKB_FRAGS 6
+
+typedef struct skb_frag_struct skb_frag_t;
+
+struct skb_frag_struct
+{
+ struct page *page;
+ __u16 page_offset;
+ __u16 size;
+};
+
+/* This data is invariant across clones and lives at
+ * the end of the header data, ie. at skb->end.
+ */
+struct skb_shared_info {
+ atomic_t dataref;
+ unsigned int nr_frags;
+ struct sk_buff *frag_list;
+ skb_frag_t frags[MAX_SKB_FRAGS];
+};
+
+struct sk_buff {
+ /* These two members must be first. */
+ struct sk_buff * next; /* Next buffer in list */
+ struct sk_buff * prev; /* Previous buffer in list */
+
+ struct sk_buff_head * list; /* List we are on */
+ struct sock *sk; /* Socket we are owned by */
+ struct timeval stamp; /* Time we arrived */
+ struct net_device *dev; /* Device we arrived on/are leaving by */
+
+ /* Transport layer header */
+ union
+ {
+ struct tcphdr *th;
+ struct udphdr *uh;
+ struct icmphdr *icmph;
+ struct igmphdr *igmph;
+ struct iphdr *ipiph;
+ struct spxhdr *spxh;
+ unsigned char *raw;
+ } h;
+
+ /* Network layer header */
+ union
+ {
+ struct iphdr *iph;
+ struct ipv6hdr *ipv6h;
+ struct arphdr *arph;
+ struct ipxhdr *ipxh;
+ unsigned char *raw;
+ } nh;
+
+ /* Link layer header */
+ union
+ {
+ struct ethhdr *ethernet;
+ unsigned char *raw;
+ } mac;
+
+ struct dst_entry *dst;
+
+ /*
+ * This is the control buffer. It is free to use for every
+ * layer. Please put your private variables there. If you
+ * want to keep them across layers you have to do a skb_clone()
+ * first. This is owned by whoever has the skb queued ATM.
+ */
+ char cb[48];
+
+ unsigned int len; /* Length of actual data */
+ unsigned int data_len;
+ unsigned int csum; /* Checksum */
+ unsigned char __unused, /* Dead field, may be reused */
+ cloned, /* head may be cloned (check refcnt to be sure). */
+ pkt_type, /* Packet class */
+ ip_summed; /* Driver fed us an IP checksum */
+ __u32 priority; /* Packet queueing priority */
+ atomic_t users; /* User count - see datagram.c,tcp.c */
+ unsigned short protocol; /* Packet protocol from driver. */
+ unsigned short security; /* Security level of packet */
+ unsigned int truesize; /* Buffer size */
+
+ unsigned char *head; /* Head of buffer */
+ unsigned char *data; /* Data head pointer */
+ unsigned char *tail; /* Tail pointer */
+ unsigned char *end; /* End pointer */
+
+ void (*destructor)(struct sk_buff *); /* Destruct function */
+#ifdef CONFIG_NETFILTER
+ /* Can be used for communication between hooks. */
+ unsigned long nfmark;
+ /* Cache info */
+ __u32 nfcache;
+ /* Associated connection, if any */
+ struct nf_ct_info *nfct;
+#ifdef CONFIG_NETFILTER_DEBUG
+ unsigned int nf_debug;
+#endif
+#endif /*CONFIG_NETFILTER*/
+
+#if defined(CONFIG_HIPPI)
+ union{
+ __u32 ifield;
+ } private;
+#endif
+
+#ifdef CONFIG_NET_SCHED
+ __u32 tc_index; /* traffic control index */
+#endif
+};
+
+#define SK_WMEM_MAX 65535
+#define SK_RMEM_MAX 65535
+
+#if 1
+//#ifdef __KERNEL__
+/*
+ * Handling routines are only of interest to the kernel
+ */
+
+extern void __kfree_skb(struct sk_buff *skb);
+extern struct sk_buff * alloc_skb(unsigned int size, int priority);
+extern void kfree_skbmem(struct sk_buff *skb);
+extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority);
+extern struct sk_buff * skb_copy(const struct sk_buff *skb, int priority);
+extern struct sk_buff * pskb_copy(struct sk_buff *skb, int gfp_mask);
+extern int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, int gfp_mask);
+extern struct sk_buff * skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom);
+extern struct sk_buff * skb_copy_expand(const struct sk_buff *skb,
+ int newheadroom,
+ int newtailroom,
+ int priority);
+#define dev_kfree_skb(a) kfree_skb(a)
+extern void skb_over_panic(struct sk_buff *skb, int len, void *here);
+extern void skb_under_panic(struct sk_buff *skb, int len, void *here);
+
+/* Internal */
+#define skb_shinfo(SKB) ((struct skb_shared_info *)((SKB)->end))
+
+/**
+ * skb_queue_empty - check if a queue is empty
+ * @list: queue head
+ *
+ * Returns true if the queue is empty, false otherwise.
+ */
+
+static inline int skb_queue_empty(struct sk_buff_head *list)
+{
+ return (list->next == (struct sk_buff *) list);
+}
+
+/**
+ * skb_get - reference buffer
+ * @skb: buffer to reference
+ *
+ * Makes another reference to a socket buffer and returns a pointer
+ * to the buffer.
+ */
+
+static inline struct sk_buff *skb_get(struct sk_buff *skb)
+{
+ atomic_inc(&skb->users);
+ return skb;
+}
+
+/*
+ * If users==1, we are the only owner and are can avoid redundant
+ * atomic change.
+ */
+
+/**
+ * kfree_skb - free an sk_buff
+ * @skb: buffer to free
+ *
+ * Drop a reference to the buffer and free it if the usage count has
+ * hit zero.
+ */
+
+static inline void kfree_skb(struct sk_buff *skb)
+{
+ if (atomic_read(&skb->users) == 1 || atomic_dec_and_test(&skb->users))
+ __kfree_skb(skb);
+}
+
+/* Use this if you didn't touch the skb state [for fast switching] */
+static inline void kfree_skb_fast(struct sk_buff *skb)
+{
+ if (atomic_read(&skb->users) == 1 || atomic_dec_and_test(&skb->users))
+ kfree_skbmem(skb);
+}
+
+/**
+ * skb_cloned - is the buffer a clone
+ * @skb: buffer to check
+ *
+ * Returns true if the buffer was generated with skb_clone() and is
+ * one of multiple shared copies of the buffer. Cloned buffers are
+ * shared data so must not be written to under normal circumstances.
+ */
+
+static inline int skb_cloned(struct sk_buff *skb)
+{
+ return skb->cloned && atomic_read(&skb_shinfo(skb)->dataref) != 1;
+}
+
+/**
+ * skb_shared - is the buffer shared
+ * @skb: buffer to check
+ *
+ * Returns true if more than one person has a reference to this
+ * buffer.
+ */
+
+static inline int skb_shared(struct sk_buff *skb)
+{
+ return (atomic_read(&skb->users) != 1);
+}
+
+/**
+ * skb_share_check - check if buffer is shared and if so clone it
+ * @skb: buffer to check
+ * @pri: priority for memory allocation
+ *
+ * If the buffer is shared the buffer is cloned and the old copy
+ * drops a reference. A new clone with a single reference is returned.
+ * If the buffer is not shared the original buffer is returned. When
+ * being called from interrupt status or with spinlocks held pri must
+ * be GFP_ATOMIC.
+ *
+ * NULL is returned on a memory allocation failure.
+ */
+
+static inline struct sk_buff *skb_share_check(struct sk_buff *skb, int pri)
+{
+ if (skb_shared(skb)) {
+ struct sk_buff *nskb;
+ nskb = skb_clone(skb, pri);
+ kfree_skb(skb);
+ return nskb;
+ }
+ return skb;
+}
+
+
+/*
+ * Copy shared buffers into a new sk_buff. We effectively do COW on
+ * packets to handle cases where we have a local reader and forward
+ * and a couple of other messy ones. The normal one is tcpdumping
+ * a packet thats being forwarded.
+ */
+
+/**
+ * skb_unshare - make a copy of a shared buffer
+ * @skb: buffer to check
+ * @pri: priority for memory allocation
+ *
+ * If the socket buffer is a clone then this function creates a new
+ * copy of the data, drops a reference count on the old copy and returns
+ * the new copy with the reference count at 1. If the buffer is not a clone
+ * the original buffer is returned. When called with a spinlock held or
+ * from interrupt state @pri must be %GFP_ATOMIC
+ *
+ * %NULL is returned on a memory allocation failure.
+ */
+
+static inline struct sk_buff *skb_unshare(struct sk_buff *skb, int pri)
+{
+ struct sk_buff *nskb;
+ if(!skb_cloned(skb))
+ return skb;
+ nskb=skb_copy(skb, pri);
+ kfree_skb(skb); /* Free our shared copy */
+ return nskb;
+}
+
+/**
+ * skb_peek
+ * @list_: list to peek at
+ *
+ * Peek an &sk_buff. Unlike most other operations you _MUST_
+ * be careful with this one. A peek leaves the buffer on the
+ * list and someone else may run off with it. You must hold
+ * the appropriate locks or have a private queue to do this.
+ *
+ * Returns %NULL for an empty list or a pointer to the head element.
+ * The reference count is not incremented and the reference is therefore
+ * volatile. Use with caution.
+ */
+
+static inline struct sk_buff *skb_peek(struct sk_buff_head *list_)
+{
+ struct sk_buff *list = ((struct sk_buff *)list_)->next;
+ if (list == (struct sk_buff *)list_)
+ list = NULL;
+ return list;
+}
+
+/**
+ * skb_peek_tail
+ * @list_: list to peek at
+ *
+ * Peek an &sk_buff. Unlike most other operations you _MUST_
+ * be careful with this one. A peek leaves the buffer on the
+ * list and someone else may run off with it. You must hold
+ * the appropriate locks or have a private queue to do this.
+ *
+ * Returns %NULL for an empty list or a pointer to the tail element.
+ * The reference count is not incremented and the reference is therefore
+ * volatile. Use with caution.
+ */
+
+static inline struct sk_buff *skb_peek_tail(struct sk_buff_head *list_)
+{
+ struct sk_buff *list = ((struct sk_buff *)list_)->prev;
+ if (list == (struct sk_buff *)list_)
+ list = NULL;
+ return list;
+}
+
+/**
+ * skb_queue_len - get queue length
+ * @list_: list to measure
+ *
+ * Return the length of an &sk_buff queue.
+ */
+
+static inline __u32 skb_queue_len(struct sk_buff_head *list_)
+{
+ return(list_->qlen);
+}
+
+static inline void skb_queue_head_init(struct sk_buff_head *list)
+{
+ spin_lock_init(&list->lock);
+ list->prev = (struct sk_buff *)list;
+ list->next = (struct sk_buff *)list;
+ list->qlen = 0;
+}
+
+/*
+ * Insert an sk_buff at the start of a list.
+ *
+ * The "__skb_xxxx()" functions are the non-atomic ones that
+ * can only be called with interrupts disabled.
+ */
+
+/**
+ * __skb_queue_head - queue a buffer at the list head
+ * @list: list to use
+ * @newsk: buffer to queue
+ *
+ * Queue a buffer at the start of a list. This function takes no locks
+ * and you must therefore hold required locks before calling it.
+ *
+ * A buffer cannot be placed on two lists at the same time.
+ */
+
+static inline void __skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk)
+{
+ struct sk_buff *prev, *next;
+
+ newsk->list = list;
+ list->qlen++;
+ prev = (struct sk_buff *)list;
+ next = prev->next;
+ newsk->next = next;
+ newsk->prev = prev;
+ next->prev = newsk;
+ prev->next = newsk;
+}
+
+
+/**
+ * skb_queue_head - queue a buffer at the list head
+ * @list: list to use
+ * @newsk: buffer to queue
+ *
+ * Queue a buffer at the start of the list. This function takes the
+ * list lock and can be used safely with other locking &sk_buff functions
+ * safely.
+ *
+ * A buffer cannot be placed on two lists at the same time.
+ */
+
+static inline void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&list->lock, flags);
+ __skb_queue_head(list, newsk);
+ spin_unlock_irqrestore(&list->lock, flags);
+}
+
+/**
+ * __skb_queue_tail - queue a buffer at the list tail
+ * @list: list to use
+ * @newsk: buffer to queue
+ *
+ * Queue a buffer at the end of a list. This function takes no locks
+ * and you must therefore hold required locks before calling it.
+ *
+ * A buffer cannot be placed on two lists at the same time.
+ */
+
+
+static inline void __skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)
+{
+ struct sk_buff *prev, *next;
+
+ newsk->list = list;
+ list->qlen++;
+ next = (struct sk_buff *)list;
+ prev = next->prev;
+ newsk->next = next;
+ newsk->prev = prev;
+ next->prev = newsk;
+ prev->next = newsk;
+}
+
+/**
+ * skb_queue_tail - queue a buffer at the list tail
+ * @list: list to use
+ * @newsk: buffer to queue
+ *
+ * Queue a buffer at the tail of the list. This function takes the
+ * list lock and can be used safely with other locking &sk_buff functions
+ * safely.
+ *
+ * A buffer cannot be placed on two lists at the same time.
+ */
+
+static inline void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&list->lock, flags);
+ __skb_queue_tail(list, newsk);
+ spin_unlock_irqrestore(&list->lock, flags);
+}
+
+/**
+ * __skb_dequeue - remove from the head of the queue
+ * @list: list to dequeue from
+ *
+ * Remove the head of the list. This function does not take any locks
+ * so must be used with appropriate locks held only. The head item is
+ * returned or %NULL if the list is empty.
+ */
+
+static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list)
+{
+ struct sk_buff *next, *prev, *result;
+
+ prev = (struct sk_buff *) list;
+ next = prev->next;
+ result = NULL;
+ if (next != prev) {
+ result = next;
+ next = next->next;
+ list->qlen--;
+ next->prev = prev;
+ prev->next = next;
+ result->next = NULL;
+ result->prev = NULL;
+ result->list = NULL;
+ }
+ return result;
+}
+
+/**
+ * skb_dequeue - remove from the head of the queue
+ * @list: list to dequeue from
+ *
+ * Remove the head of the list. The list lock is taken so the function
+ * may be used safely with other locking list functions. The head item is
+ * returned or %NULL if the list is empty.
+ */
+
+static inline struct sk_buff *skb_dequeue(struct sk_buff_head *list)
+{
+ unsigned long flags;
+ struct sk_buff *result;
+
+ spin_lock_irqsave(&list->lock, flags);
+ result = __skb_dequeue(list);
+ spin_unlock_irqrestore(&list->lock, flags);
+ return result;
+}
+
+/*
+ * Insert a packet on a list.
+ */
+
+static inline void __skb_insert(struct sk_buff *newsk,
+ struct sk_buff * prev, struct sk_buff *next,
+ struct sk_buff_head * list)
+{
+ newsk->next = next;
+ newsk->prev = prev;
+ next->prev = newsk;
+ prev->next = newsk;
+ newsk->list = list;
+ list->qlen++;
+}
+
+/**
+ * skb_insert - insert a buffer
+ * @old: buffer to insert before
+ * @newsk: buffer to insert
+ *
+ * Place a packet before a given packet in a list. The list locks are taken
+ * and this function is atomic with respect to other list locked calls
+ * A buffer cannot be placed on two lists at the same time.
+ */
+
+static inline void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&old->list->lock, flags);
+ __skb_insert(newsk, old->prev, old, old->list);
+ spin_unlock_irqrestore(&old->list->lock, flags);
+}
+
+/*
+ * Place a packet after a given packet in a list.
+ */
+
+static inline void __skb_append(struct sk_buff *old, struct sk_buff *newsk)
+{
+ __skb_insert(newsk, old, old->next, old->list);
+}
+
+/**
+ * skb_append - append a buffer
+ * @old: buffer to insert after
+ * @newsk: buffer to insert
+ *
+ * Place a packet after a given packet in a list. The list locks are taken
+ * and this function is atomic with respect to other list locked calls.
+ * A buffer cannot be placed on two lists at the same time.
+ */
+
+
+static inline void skb_append(struct sk_buff *old, struct sk_buff *newsk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&old->list->lock, flags);
+ __skb_append(old, newsk);
+ spin_unlock_irqrestore(&old->list->lock, flags);
+}
+
+/*
+ * remove sk_buff from list. _Must_ be called atomically, and with
+ * the list known..
+ */
+
+static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
+{
+ struct sk_buff * next, * prev;
+
+ list->qlen--;
+ next = skb->next;
+ prev = skb->prev;
+ skb->next = NULL;
+ skb->prev = NULL;
+ skb->list = NULL;
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * skb_unlink - remove a buffer from a list
+ * @skb: buffer to remove
+ *
+ * Place a packet after a given packet in a list. The list locks are taken
+ * and this function is atomic with respect to other list locked calls
+ *
+ * Works even without knowing the list it is sitting on, which can be
+ * handy at times. It also means that THE LIST MUST EXIST when you
+ * unlink. Thus a list must have its contents unlinked before it is
+ * destroyed.
+ */
+
+static inline void skb_unlink(struct sk_buff *skb)
+{
+ struct sk_buff_head *list = skb->list;
+
+ if(list) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&list->lock, flags);
+ if(skb->list == list)
+ __skb_unlink(skb, skb->list);
+ spin_unlock_irqrestore(&list->lock, flags);
+ }
+}
+
+/* XXX: more streamlined implementation */
+
+/**
+ * __skb_dequeue_tail - remove from the tail of the queue
+ * @list: list to dequeue from
+ *
+ * Remove the tail of the list. This function does not take any locks
+ * so must be used with appropriate locks held only. The tail item is
+ * returned or %NULL if the list is empty.
+ */
+
+static inline struct sk_buff *__skb_dequeue_tail(struct sk_buff_head *list)
+{
+ struct sk_buff *skb = skb_peek_tail(list);
+ if (skb)
+ __skb_unlink(skb, list);
+ return skb;
+}
+
+/**
+ * skb_dequeue - remove from the head of the queue
+ * @list: list to dequeue from
+ *
+ * Remove the head of the list. The list lock is taken so the function
+ * may be used safely with other locking list functions. The tail item is
+ * returned or %NULL if the list is empty.
+ */
+
+static inline struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list)
+{
+ unsigned long flags;
+ struct sk_buff *result;
+
+ spin_lock_irqsave(&list->lock, flags);
+ result = __skb_dequeue_tail(list);
+ spin_unlock_irqrestore(&list->lock, flags);
+ return result;
+}
+
+static inline int skb_is_nonlinear(const struct sk_buff *skb)
+{
+ return skb->data_len;
+}
+
+static inline int skb_headlen(const struct sk_buff *skb)
+{
+ return skb->len - skb->data_len;
+}
+
+#define SKB_PAGE_ASSERT(skb) do { if (skb_shinfo(skb)->nr_frags) out_of_line_bug(); } while (0)
+#define SKB_FRAG_ASSERT(skb) do { if (skb_shinfo(skb)->frag_list) out_of_line_bug(); } while (0)
+#define SKB_LINEAR_ASSERT(skb) do { if (skb_is_nonlinear(skb)) out_of_line_bug(); } while (0)
+
+/*
+ * Add data to an sk_buff
+ */
+
+static inline unsigned char *__skb_put(struct sk_buff *skb, unsigned int len)
+{
+ unsigned char *tmp=skb->tail;
+ SKB_LINEAR_ASSERT(skb);
+ skb->tail+=len;
+ skb->len+=len;
+ return tmp;
+}
+
+/**
+ * skb_put - add data to a buffer
+ * @skb: buffer to use
+ * @len: amount of data to add
+ *
+ * This function extends the used data area of the buffer. If this would
+ * exceed the total buffer size the kernel will panic. A pointer to the
+ * first byte of the extra data is returned.
+ */
+
+static inline unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
+{
+#if 0
+ unsigned char *tmp=skb->tail;
+ SKB_LINEAR_ASSERT(skb);
+ skb->tail+=len;
+ skb->len+=len;
+ if(skb->tail>skb->end) {
+ skb_over_panic(skb, len, current_text_addr());
+ }
+ return tmp;
+#else
+return NULL;
+#endif
+}
+
+static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len)
+{
+ skb->data-=len;
+ skb->len+=len;
+ return skb->data;
+}
+
+/**
+ * skb_push - add data to the start of a buffer
+ * @skb: buffer to use
+ * @len: amount of data to add
+ *
+ * This function extends the used data area of the buffer at the buffer
+ * start. If this would exceed the total buffer headroom the kernel will
+ * panic. A pointer to the first byte of the extra data is returned.
+ */
+
+static inline unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
+{
+#if 0
+ skb->data-=len;
+ skb->len+=len;
+ if(skb->data<skb->head) {
+ skb_under_panic(skb, len, current_text_addr());
+ }
+ return skb->data;
+#else
+ return NULL;
+#endif
+}
+
+static inline char *__skb_pull(struct sk_buff *skb, unsigned int len)
+{
+ skb->len-=len;
+ if (skb->len < skb->data_len)
+ out_of_line_bug();
+ return skb->data+=len;
+}
+
+/**
+ * skb_pull - remove data from the start of a buffer
+ * @skb: buffer to use
+ * @len: amount of data to remove
+ *
+ * This function removes data from the start of a buffer, returning
+ * the memory to the headroom. A pointer to the next data in the buffer
+ * is returned. Once the data has been pulled future pushes will overwrite
+ * the old data.
+ */
+
+static inline unsigned char * skb_pull(struct sk_buff *skb, unsigned int len)
+{
+ if (len > skb->len)
+ return NULL;
+ return __skb_pull(skb,len);
+}
+
+extern unsigned char * __pskb_pull_tail(struct sk_buff *skb, int delta);
+
+static inline char *__pskb_pull(struct sk_buff *skb, unsigned int len)
+{
+ if (len > skb_headlen(skb) &&
+ __pskb_pull_tail(skb, len-skb_headlen(skb)) == NULL)
+ return NULL;
+ skb->len -= len;
+ return skb->data += len;
+}
+
+static inline unsigned char * pskb_pull(struct sk_buff *skb, unsigned int len)
+{
+ if (len > skb->len)
+ return NULL;
+ return __pskb_pull(skb,len);
+}
+
+static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len)
+{
+ if (len <= skb_headlen(skb))
+ return 1;
+ if (len > skb->len)
+ return 0;
+ return (__pskb_pull_tail(skb, len-skb_headlen(skb)) != NULL);
+}
+
+/**
+ * skb_headroom - bytes at buffer head
+ * @skb: buffer to check
+ *
+ * Return the number of bytes of free space at the head of an &sk_buff.
+ */
+
+static inline int skb_headroom(const struct sk_buff *skb)
+{
+ return skb->data-skb->head;
+}
+
+/**
+ * skb_tailroom - bytes at buffer end
+ * @skb: buffer to check
+ *
+ * Return the number of bytes of free space at the tail of an sk_buff
+ */
+
+static inline int skb_tailroom(const struct sk_buff *skb)
+{
+ return skb_is_nonlinear(skb) ? 0 : skb->end-skb->tail;
+}
+
+/**
+ * skb_reserve - adjust headroom
+ * @skb: buffer to alter
+ * @len: bytes to move
+ *
+ * Increase the headroom of an empty &sk_buff by reducing the tail
+ * room. This is only allowed for an empty buffer.
+ */
+
+static inline void skb_reserve(struct sk_buff *skb, unsigned int len)
+{
+ skb->data+=len;
+ skb->tail+=len;
+}
+
+extern int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc);
+
+static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
+{
+ if (!skb->data_len) {
+ skb->len = len;
+ skb->tail = skb->data+len;
+ } else {
+ ___pskb_trim(skb, len, 0);
+ }
+}
+
+/**
+ * skb_trim - remove end from a buffer
+ * @skb: buffer to alter
+ * @len: new length
+ *
+ * Cut the length of a buffer down by removing data from the tail. If
+ * the buffer is already under the length specified it is not modified.
+ */
+
+static inline void skb_trim(struct sk_buff *skb, unsigned int len)
+{
+ if (skb->len > len) {
+ __skb_trim(skb, len);
+ }
+}
+
+
+static inline int __pskb_trim(struct sk_buff *skb, unsigned int len)
+{
+ if (!skb->data_len) {
+ skb->len = len;
+ skb->tail = skb->data+len;
+ return 0;
+ } else {
+ return ___pskb_trim(skb, len, 1);
+ }
+}
+
+static inline int pskb_trim(struct sk_buff *skb, unsigned int len)
+{
+ if (len < skb->len)
+ return __pskb_trim(skb, len);
+ return 0;
+}
+
+/**
+ * skb_orphan - orphan a buffer
+ * @skb: buffer to orphan
+ *
+ * If a buffer currently has an owner then we call the owner's
+ * destructor function and make the @skb unowned. The buffer continues
+ * to exist but is no longer charged to its former owner.
+ */
+
+
+static inline void skb_orphan(struct sk_buff *skb)
+{
+ if (skb->destructor)
+ skb->destructor(skb);
+ skb->destructor = NULL;
+ skb->sk = NULL;
+}
+
+/**
+ * skb_purge - empty a list
+ * @list: list to empty
+ *
+ * Delete all buffers on an &sk_buff list. Each buffer is removed from
+ * the list and one reference dropped. This function takes the list
+ * lock and is atomic with respect to other list locking functions.
+ */
+
+
+static inline void skb_queue_purge(struct sk_buff_head *list)
+{
+ struct sk_buff *skb;
+ while ((skb=skb_dequeue(list))!=NULL)
+ kfree_skb(skb);
+}
+
+/**
+ * __skb_purge - empty a list
+ * @list: list to empty
+ *
+ * Delete all buffers on an &sk_buff list. Each buffer is removed from
+ * the list and one reference dropped. This function does not take the
+ * list lock and the caller must hold the relevant locks to use it.
+ */
+
+
+static inline void __skb_queue_purge(struct sk_buff_head *list)
+{
+ struct sk_buff *skb;
+ while ((skb=__skb_dequeue(list))!=NULL)
+ kfree_skb(skb);
+}
+
+/**
+ * __dev_alloc_skb - allocate an skbuff for sending
+ * @length: length to allocate
+ * @gfp_mask: get_free_pages mask, passed to alloc_skb
+ *
+ * Allocate a new &sk_buff and assign it a usage count of one. The
+ * buffer has unspecified headroom built in. Users should allocate
+ * the headroom they think they need without accounting for the
+ * built in space. The built in space is used for optimisations.
+ *
+ * %NULL is returned in there is no free memory.
+ */
+
+static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
+ int gfp_mask)
+{
+ struct sk_buff *skb;
+
+ skb = alloc_skb(length+16, gfp_mask);
+ if (skb)
+ skb_reserve(skb,16);
+ return skb;
+}
+
+/**
+ * dev_alloc_skb - allocate an skbuff for sending
+ * @length: length to allocate
+ *
+ * Allocate a new &sk_buff and assign it a usage count of one. The
+ * buffer has unspecified headroom built in. Users should allocate
+ * the headroom they think they need without accounting for the
+ * built in space. The built in space is used for optimisations.
+ *
+ * %NULL is returned in there is no free memory. Although this function
+ * allocates memory it can be called from an interrupt.
+ */
+
+static inline struct sk_buff *dev_alloc_skb(unsigned int length)
+{
+#if 0
+ return __dev_alloc_skb(length, GFP_ATOMIC);
+#else
+ return NULL;
+#endif
+}
+
+/**
+ * skb_cow - copy header of skb when it is required
+ * @skb: buffer to cow
+ * @headroom: needed headroom
+ *
+ * If the skb passed lacks sufficient headroom or its data part
+ * is shared, data is reallocated. If reallocation fails, an error
+ * is returned and original skb is not changed.
+ *
+ * The result is skb with writable area skb->head...skb->tail
+ * and at least @headroom of space at head.
+ */
+
+static inline int
+skb_cow(struct sk_buff *skb, unsigned int headroom)
+{
+#if 0
+ int delta = (headroom > 16 ? headroom : 16) - skb_headroom(skb);
+
+ if (delta < 0)
+ delta = 0;
+
+ if (delta || skb_cloned(skb))
+ return pskb_expand_head(skb, (delta+15)&~15, 0, GFP_ATOMIC);
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+/**
+ * skb_linearize - convert paged skb to linear one
+ * @skb: buffer to linarize
+ * @gfp: allocation mode
+ *
+ * If there is no free memory -ENOMEM is returned, otherwise zero
+ * is returned and the old skb data released. */
+int skb_linearize(struct sk_buff *skb, int gfp);
+
+static inline void *kmap_skb_frag(const skb_frag_t *frag)
+{
+#if 0
+#ifdef CONFIG_HIGHMEM
+ if (in_irq())
+ out_of_line_bug();
+
+ local_bh_disable();
+#endif
+ return kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ);
+#else
+ return NULL;
+#endif
+}
+
+static inline void kunmap_skb_frag(void *vaddr)
+{
+#if 0
+ kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ);
+#ifdef CONFIG_HIGHMEM
+ local_bh_enable();
+#endif
+#endif
+}
+
+#define skb_queue_walk(queue, skb) \
+ for (skb = (queue)->next; \
+ (skb != (struct sk_buff *)(queue)); \
+ skb=skb->next)
+
+
+extern struct sk_buff * skb_recv_datagram(struct sock *sk,unsigned flags,int noblock, int *err);
+extern unsigned int datagram_poll(struct file *file, struct socket *sock, struct poll_table_struct *wait);
+extern int skb_copy_datagram(const struct sk_buff *from, int offset, char *to,int size);
+extern int skb_copy_datagram_iovec(const struct sk_buff *from, int offset, struct iovec *to,int size);
+extern int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, u8 *to, int len, unsigned int *csump);
+extern int skb_copy_and_csum_datagram_iovec(const struct sk_buff *skb, int hlen, struct iovec *iov);
+extern void skb_free_datagram(struct sock * sk, struct sk_buff *skb);
+
+extern unsigned int skb_checksum(const struct sk_buff *skb, int offset, int len, unsigned int csum);
+extern int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len);
+extern unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, u8 *to, int len, unsigned int csum);
+extern void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
+
+extern void skb_init(void);
+extern void skb_add_mtu(int mtu);
+
+#ifdef CONFIG_NETFILTER
+static inline void
+nf_conntrack_put(struct nf_ct_info *nfct)
+{
+ if (nfct && atomic_dec_and_test(&nfct->master->use))
+ nfct->master->destroy(nfct->master);
+}
+static inline void
+nf_conntrack_get(struct nf_ct_info *nfct)
+{
+ if (nfct)
+ atomic_inc(&nfct->master->use);
+}
+#endif
+
+
+#endif /* skbuff */
+
+
+
+
+
+struct sock;
+
+typedef struct sockaddr
+{
+ int x;
+} _sockaddr;
+
+
+struct msghdr {
+ void * msg_name; /* Socket name */
+ int msg_namelen; /* Length of name */
+ struct iovec * msg_iov; /* Data blocks */
+ __kernel_size_t msg_iovlen; /* Number of blocks */
+ void * msg_control; /* Per protocol magic (eg BSD file descriptor passing) */
+ __kernel_size_t msg_controllen; /* Length of cmsg list */
+ unsigned msg_flags;
+};
+
+
+/* IP protocol blocks we attach to sockets.
+ * socket layer -> transport layer interface
+ * transport -> network interface is defined by struct inet_proto
+ */
+struct proto {
+ void (*close)(struct sock *sk,
+ long timeout);
+ int (*connect)(struct sock *sk,
+ struct sockaddr *uaddr,
+ int addr_len);
+ int (*disconnect)(struct sock *sk, int flags);
+
+ struct sock * (*accept) (struct sock *sk, int flags, int *err);
+
+ int (*ioctl)(struct sock *sk, int cmd,
+ unsigned long arg);
+ int (*init)(struct sock *sk);
+ int (*destroy)(struct sock *sk);
+ void (*shutdown)(struct sock *sk, int how);
+ int (*setsockopt)(struct sock *sk, int level,
+ int optname, char *optval, int optlen);
+ int (*getsockopt)(struct sock *sk, int level,
+ int optname, char *optval,
+ int *option);
+ int (*sendmsg)(struct sock *sk, struct msghdr *msg,
+ int len);
+ int (*recvmsg)(struct sock *sk, struct msghdr *msg,
+ int len, int noblock, int flags,
+ int *addr_len);
+ int (*bind)(struct sock *sk,
+ struct sockaddr *uaddr, int addr_len);
+
+ int (*backlog_rcv) (struct sock *sk,
+ struct sk_buff *skb);
+
+ /* Keeping track of sk's, looking them up, and port selection methods. */
+ void (*hash)(struct sock *sk);
+ void (*unhash)(struct sock *sk);
+ int (*get_port)(struct sock *sk, unsigned short snum);
+
+ char name[32];
+
+ struct {
+ int inuse;
+ } stats[32];
+// u8 __pad[SMP_CACHE_BYTES - sizeof(int)];
+// } stats[NR_CPUS];
+};
+
+
+
+
+
+
+
+/* This defines a selective acknowledgement block. */
+struct tcp_sack_block {
+ __u32 start_seq;
+ __u32 end_seq;
+};
+
+
+struct tcp_opt {
+ int tcp_header_len; /* Bytes of tcp header to send */
+
+/*
+ * Header prediction flags
+ * 0x5?10 << 16 + snd_wnd in net byte order
+ */
+ __u32 pred_flags;
+
+/*
+ * RFC793 variables by their proper names. This means you can
+ * read the code and the spec side by side (and laugh ...)
+ * See RFC793 and RFC1122. The RFC writes these in capitals.
+ */
+ __u32 rcv_nxt; /* What we want to receive next */
+ __u32 snd_nxt; /* Next sequence we send */
+
+ __u32 snd_una; /* First byte we want an ack for */
+ __u32 snd_sml; /* Last byte of the most recently transmitted small packet */
+ __u32 rcv_tstamp; /* timestamp of last received ACK (for keepalives) */
+ __u32 lsndtime; /* timestamp of last sent data packet (for restart window) */
+
+ /* Delayed ACK control data */
+ struct {
+ __u8 pending; /* ACK is pending */
+ __u8 quick; /* Scheduled number of quick acks */
+ __u8 pingpong; /* The session is interactive */
+ __u8 blocked; /* Delayed ACK was blocked by socket lock*/
+ __u32 ato; /* Predicted tick of soft clock */
+ unsigned long timeout; /* Currently scheduled timeout */
+ __u32 lrcvtime; /* timestamp of last received data packet*/
+ __u16 last_seg_size; /* Size of last incoming segment */
+ __u16 rcv_mss; /* MSS used for delayed ACK decisions */
+ } ack;
+
+ /* Data for direct copy to user */
+ struct {
+ //struct sk_buff_head prequeue;
+ struct task_struct *task;
+ struct iovec *iov;
+ int memory;
+ int len;
+ } ucopy;
+
+ __u32 snd_wl1; /* Sequence for window update */
+ __u32 snd_wnd; /* The window we expect to receive */
+ __u32 max_window; /* Maximal window ever seen from peer */
+ __u32 pmtu_cookie; /* Last pmtu seen by socket */
+ __u16 mss_cache; /* Cached effective mss, not including SACKS */
+ __u16 mss_clamp; /* Maximal mss, negotiated at connection setup */
+ __u16 ext_header_len; /* Network protocol overhead (IP/IPv6 options) */
+ __u8 ca_state; /* State of fast-retransmit machine */
+ __u8 retransmits; /* Number of unrecovered RTO timeouts. */
+
+ __u8 reordering; /* Packet reordering metric. */
+ __u8 queue_shrunk; /* Write queue has been shrunk recently.*/
+ __u8 defer_accept; /* User waits for some data after accept() */
+
+/* RTT measurement */
+ __u8 backoff; /* backoff */
+ __u32 srtt; /* smothed round trip time << 3 */
+ __u32 mdev; /* medium deviation */
+ __u32 mdev_max; /* maximal mdev for the last rtt period */
+ __u32 rttvar; /* smoothed mdev_max */
+ __u32 rtt_seq; /* sequence number to update rttvar */
+ __u32 rto; /* retransmit timeout */
+
+ __u32 packets_out; /* Packets which are "in flight" */
+ __u32 left_out; /* Packets which leaved network */
+ __u32 retrans_out; /* Retransmitted packets out */
+
+
+/*
+ * Slow start and congestion control (see also Nagle, and Karn & Partridge)
+ */
+ __u32 snd_ssthresh; /* Slow start size threshold */
+ __u32 snd_cwnd; /* Sending congestion window */
+ __u16 snd_cwnd_cnt; /* Linear increase counter */
+ __u16 snd_cwnd_clamp; /* Do not allow snd_cwnd to grow above this */
+ __u32 snd_cwnd_used;
+ __u32 snd_cwnd_stamp;
+
+ /* Two commonly used timers in both sender and receiver paths. */
+ unsigned long timeout;
+ struct timer_list retransmit_timer; /* Resend (no ack) */
+ struct timer_list delack_timer; /* Ack delay */
+
+ struct sk_buff_head out_of_order_queue; /* Out of order segments go here */
+
+ struct tcp_func *af_specific; /* Operations which are AF_INET{4,6} specific */
+ struct sk_buff *send_head; /* Front of stuff to transmit */
+ struct page *sndmsg_page; /* Cached page for sendmsg */
+ u32 sndmsg_off; /* Cached offset for sendmsg */
+
+ __u32 rcv_wnd; /* Current receiver window */
+ __u32 rcv_wup; /* rcv_nxt on last window update sent */
+ __u32 write_seq; /* Tail(+1) of data held in tcp send buffer */
+ __u32 pushed_seq; /* Last pushed seq, required to talk to windows */
+ __u32 copied_seq; /* Head of yet unread data */
+/*
+ * Options received (usually on last packet, some only on SYN packets).
+ */
+ char tstamp_ok, /* TIMESTAMP seen on SYN packet */
+ wscale_ok, /* Wscale seen on SYN packet */
+ sack_ok; /* SACK seen on SYN packet */
+ char saw_tstamp; /* Saw TIMESTAMP on last packet */
+ __u8 snd_wscale; /* Window scaling received from sender */
+ __u8 rcv_wscale; /* Window scaling to send to receiver */
+ __u8 nonagle; /* Disable Nagle algorithm? */
+ __u8 keepalive_probes; /* num of allowed keep alive probes */
+
+/* PAWS/RTTM data */
+ __u32 rcv_tsval; /* Time stamp value */
+ __u32 rcv_tsecr; /* Time stamp echo reply */
+ __u32 ts_recent; /* Time stamp to echo next */
+ long ts_recent_stamp;/* Time we stored ts_recent (for aging) */
+
+/* SACKs data */
+ __u16 user_mss; /* mss requested by user in ioctl */
+ __u8 dsack; /* D-SACK is scheduled */
+ __u8 eff_sacks; /* Size of SACK array to send with next packet */
+ struct tcp_sack_block duplicate_sack[1]; /* D-SACK block */
+ struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/
+
+ __u32 window_clamp; /* Maximal window to advertise */
+ __u32 rcv_ssthresh; /* Current window clamp */
+ __u8 probes_out; /* unanswered 0 window probes */
+ __u8 num_sacks; /* Number of SACK blocks */
+ __u16 advmss; /* Advertised MSS */
+
+ __u8 syn_retries; /* num of allowed syn retries */
+ __u8 ecn_flags; /* ECN status bits. */
+ __u16 prior_ssthresh; /* ssthresh saved at recovery start */
+ __u32 lost_out; /* Lost packets */
+ __u32 sacked_out; /* SACK'd packets */
+ __u32 fackets_out; /* FACK'd packets */
+ __u32 high_seq; /* snd_nxt at onset of congestion */
+
+ __u32 retrans_stamp; /* Timestamp of the last retransmit,
+ * also used in SYN-SENT to remember stamp of
+ * the first SYN. */
+ __u32 undo_marker; /* tracking retrans started here. */
+ int undo_retrans; /* number of undoable retransmissions. */
+ __u32 urg_seq; /* Seq of received urgent pointer */
+ __u16 urg_data; /* Saved octet of OOB data and control flags */
+ __u8 pending; /* Scheduled timer event */
+ __u8 urg_mode; /* In urgent mode */
+ __u32 snd_up; /* Urgent pointer */
+
+ /* The syn_wait_lock is necessary only to avoid tcp_get_info having
+ * to grab the main lock sock while browsing the listening hash
+ * (otherwise it's deadlock prone).
+ * This lock is acquired in read mode only from tcp_get_info() and
+ * it's acquired in write mode _only_ from code that is actively
+ * changing the syn_wait_queue. All readers that are holding
+ * the master sock lock don't need to grab this lock in read mode
+ * too as the syn_wait_queue writes are always protected from
+ * the main sock lock.
+ */
+ rwlock_t syn_wait_lock;
+ struct tcp_listen_opt *listen_opt;
+
+ /* FIFO of established children */
+ struct open_request *accept_queue;
+ struct open_request *accept_queue_tail;
+
+ int write_pending; /* A write to socket waits to start. */
+
+ unsigned int keepalive_time; /* time before keep alive takes place */
+ unsigned int keepalive_intvl; /* time interval between keep alive probes */
+ int linger2;
+
+ unsigned long last_synq_overflow;
+};
+
+
+
+
+/* This is the per-socket lock. The spinlock provides a synchronization
+ * between user contexts and software interrupt processing, whereas the
+ * mini-semaphore synchronizes multiple users amongst themselves.
+ */
+typedef struct {
+ spinlock_t slock;
+ unsigned int users;
+ wait_queue_head_t wq;
+} socket_lock_t;
+
+struct sock {
+ /* Socket demultiplex comparisons on incoming packets. */
+ __u32 daddr; /* Foreign IPv4 addr */
+ __u32 rcv_saddr; /* Bound local IPv4 addr */
+ __u16 dport; /* Destination port */
+ unsigned short num; /* Local port */
+ int bound_dev_if; /* Bound device index if != 0 */
+
+ /* Main hash linkage for various protocol lookup tables. */
+ struct sock *next;
+ struct sock **pprev;
+ struct sock *bind_next;
+ struct sock **bind_pprev;
+
+ volatile unsigned char state, /* Connection state */
+ zapped; /* In ax25 & ipx means not linked */
+ __u16 sport; /* Source port */
+
+ unsigned short family; /* Address family */
+ unsigned char reuse; /* SO_REUSEADDR setting */
+ unsigned char shutdown;
+ atomic_t refcnt; /* Reference count */
+
+ socket_lock_t lock; /* Synchronizer... */
+ int rcvbuf; /* Size of receive buffer in bytes */
+
+ wait_queue_head_t *sleep; /* Sock wait queue */
+ struct dst_entry *dst_cache; /* Destination cache */
+ rwlock_t dst_lock;
+ atomic_t rmem_alloc; /* Receive queue bytes committed */
+ struct sk_buff_head receive_queue; /* Incoming packets */
+ atomic_t wmem_alloc; /* Transmit queue bytes committed */
+ struct sk_buff_head write_queue; /* Packet sending queue */
+ atomic_t omem_alloc; /* "o" is "option" or "other" */
+ int wmem_queued; /* Persistent queue size */
+ int forward_alloc; /* Space allocated forward. */
+ __u32 saddr; /* Sending source */
+ unsigned int allocation; /* Allocation mode */
+ int sndbuf; /* Size of send buffer in bytes */
+ struct sock *prev;
+
+ /* Not all are volatile, but some are, so we might as well say they all are.
+ * XXX Make this a flag word -DaveM
+ */
+ volatile char dead,
+ done,
+ urginline,
+ keepopen,
+ linger,
+ destroy,
+ no_check,
+ broadcast,
+ bsdism;
+ unsigned char debug;
+ unsigned char rcvtstamp;
+ unsigned char use_write_queue;
+ unsigned char userlocks;
+ /* Hole of 3 bytes. Try to pack. */
+ int route_caps;
+ int proc;
+ unsigned long lingertime;
+
+ int hashent;
+ struct sock *pair;
+
+ /* The backlog queue is special, it is always used with
+ * the per-socket spinlock held and requires low latency
+ * access. Therefore we special case it's implementation.
+ */
+ struct {
+ struct sk_buff *head;
+ struct sk_buff *tail;
+ } backlog;
+
+ rwlock_t callback_lock;
+
+ /* Error queue, rarely used. */
+ struct sk_buff_head error_queue;
+
+ struct proto *prot;
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ union {
+ struct ipv6_pinfo af_inet6;
+ } net_pinfo;
+#endif
+
+ union {
+ struct tcp_opt af_tcp;
+#if defined(CONFIG_INET) || defined (CONFIG_INET_MODULE)
+ struct raw_opt tp_raw4;
+#endif
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ struct raw6_opt tp_raw;
+#endif /* CONFIG_IPV6 */
+#if defined(CONFIG_SPX) || defined (CONFIG_SPX_MODULE)
+ struct spx_opt af_spx;
+#endif /* CONFIG_SPX */
+
+ } tp_pinfo;
+
+ int err, err_soft; /* Soft holds errors that don't
+ cause failure but are the cause
+ of a persistent failure not just
+ 'timed out' */
+ unsigned short ack_backlog;
+ unsigned short max_ack_backlog;
+ __u32 priority;
+ unsigned short type;
+ unsigned char localroute; /* Route locally only */
+ unsigned char protocol;
+// struct ucred peercred;
+ int rcvlowat;
+ long rcvtimeo;
+ long sndtimeo;
+
+#ifdef CONFIG_FILTER
+ /* Socket Filtering Instructions */
+ struct sk_filter *filter;
+#endif /* CONFIG_FILTER */
+
+ /* This is where all the private (optional) areas that don't
+ * overlap will eventually live.
+ */
+ union {
+ void *destruct_hook;
+// struct unix_opt af_unix;
+#if defined(CONFIG_INET) || defined (CONFIG_INET_MODULE)
+ struct inet_opt af_inet;
+#endif
+#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE)
+ struct atalk_sock af_at;
+#endif
+#if defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE)
+ struct ipx_opt af_ipx;
+#endif
+#if defined (CONFIG_DECNET) || defined(CONFIG_DECNET_MODULE)
+ struct dn_scp dn;
+#endif
+#if defined (CONFIG_PACKET) || defined(CONFIG_PACKET_MODULE)
+ struct packet_opt *af_packet;
+#endif
+#if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE)
+ x25_cb *x25;
+#endif
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+ ax25_cb *ax25;
+#endif
+#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)
+ nr_cb *nr;
+#endif
+#if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
+ rose_cb *rose;
+#endif
+#if defined(CONFIG_PPPOE) || defined(CONFIG_PPPOE_MODULE)
+ struct pppox_opt *pppox;
+#endif
+ struct netlink_opt *af_netlink;
+#if defined(CONFIG_ECONET) || defined(CONFIG_ECONET_MODULE)
+ struct econet_opt *af_econet;
+#endif
+#if defined(CONFIG_ATM) || defined(CONFIG_ATM_MODULE)
+ struct atm_vcc *af_atm;
+#endif
+#if defined(CONFIG_IRDA) || defined(CONFIG_IRDA_MODULE)
+ struct irda_sock *irda;
+#endif
+#if defined(CONFIG_WAN_ROUTER) || defined(CONFIG_WAN_ROUTER_MODULE)
+ struct wanpipe_opt *af_wanpipe;
+#endif
+ } protinfo;
+
+
+ /* This part is used for the timeout functions. */
+ struct timer_list timer; /* This is the sock cleanup timer. */
+ struct timeval stamp;
+
+ /* Identd and reporting IO signals */
+ struct socket *socket;
+
+ /* RPC layer private data */
+ void *user_data;
+
+ /* Callbacks */
+ void (*state_change)(struct sock *sk);
+ void (*data_ready)(struct sock *sk,int bytes);
+ void (*write_space)(struct sock *sk);
+ void (*error_report)(struct sock *sk);
+
+ int (*backlog_rcv) (struct sock *sk,
+ struct sk_buff *skb);
+ void (*destruct)(struct sock *sk);
+};
+
+
+
+
+#if 1 /* dst (_NET_DST_H) */
+
+#if 0
+#include <linux/config.h>
+#include <net/neighbour.h>
+#endif
+
+/*
+ * 0 - no debugging messages
+ * 1 - rare events and bugs (default)
+ * 2 - trace mode.
+ */
+#define RT_CACHE_DEBUG 0
+
+#define DST_GC_MIN (1*HZ)
+#define DST_GC_INC (5*HZ)
+#define DST_GC_MAX (120*HZ)
+
+struct sk_buff;
+
+struct dst_entry
+{
+ struct dst_entry *next;
+ atomic_t __refcnt; /* client references */
+ int __use;
+ struct net_device *dev;
+ int obsolete;
+ int flags;
+#define DST_HOST 1
+ unsigned long lastuse;
+ unsigned long expires;
+
+ unsigned mxlock;
+ unsigned pmtu;
+ unsigned window;
+ unsigned rtt;
+ unsigned rttvar;
+ unsigned ssthresh;
+ unsigned cwnd;
+ unsigned advmss;
+ unsigned reordering;
+
+ unsigned long rate_last; /* rate limiting for ICMP */
+ unsigned long rate_tokens;
+
+ int error;
+
+ struct neighbour *neighbour;
+ struct hh_cache *hh;
+
+ int (*input)(struct sk_buff*);
+ int (*output)(struct sk_buff*);
+
+#ifdef CONFIG_NET_CLS_ROUTE
+ __u32 tclassid;
+#endif
+
+ struct dst_ops *ops;
+
+ char info[0];
+};
+
+
+struct dst_ops
+{
+ unsigned short family;
+ unsigned short protocol;
+ unsigned gc_thresh;
+
+ int (*gc)(void);
+ struct dst_entry * (*check)(struct dst_entry *, __u32 cookie);
+ struct dst_entry * (*reroute)(struct dst_entry *,
+ struct sk_buff *);
+ void (*destroy)(struct dst_entry *);
+ struct dst_entry * (*negative_advice)(struct dst_entry *);
+ void (*link_failure)(struct sk_buff *);
+ int entry_size;
+
+ atomic_t entries;
+ kmem_cache_t *kmem_cachep;
+};
+
+#ifdef __KERNEL__
+
+static inline void dst_hold(struct dst_entry * dst)
+{
+ atomic_inc(&dst->__refcnt);
+}
+
+static inline
+struct dst_entry * dst_clone(struct dst_entry * dst)
+{
+ if (dst)
+ atomic_inc(&dst->__refcnt);
+ return dst;
+}
+
+static inline
+void dst_release(struct dst_entry * dst)
+{
+ if (dst)
+ atomic_dec(&dst->__refcnt);
+}
+
+extern void * dst_alloc(struct dst_ops * ops);
+extern void __dst_free(struct dst_entry * dst);
+extern void dst_destroy(struct dst_entry * dst);
+
+static inline
+void dst_free(struct dst_entry * dst)
+{
+ if (dst->obsolete > 1)
+ return;
+ if (!atomic_read(&dst->__refcnt)) {
+ dst_destroy(dst);
+ return;
+ }
+ __dst_free(dst);
+}
+
+static inline void dst_confirm(struct dst_entry *dst)
+{
+ if (dst)
+ neigh_confirm(dst->neighbour);
+}
+
+static inline void dst_negative_advice(struct dst_entry **dst_p)
+{
+ struct dst_entry * dst = *dst_p;
+ if (dst && dst->ops->negative_advice)
+ *dst_p = dst->ops->negative_advice(dst);
+}
+
+static inline void dst_link_failure(struct sk_buff *skb)
+{
+ struct dst_entry * dst = skb->dst;
+ if (dst && dst->ops && dst->ops->link_failure)
+ dst->ops->link_failure(skb);
+}
+
+static inline void dst_set_expires(struct dst_entry *dst, int timeout)
+{
+ unsigned long expires = jiffies + timeout;
+
+ if (expires == 0)
+ expires = 1;
+
+ if (dst->expires == 0 || (long)(dst->expires - expires) > 0)
+ dst->expires = expires;
+}
+
+extern void dst_init(void);
+
+#endif /* dst */
+
+
+
+#if 1
+/* dummy types */
+
+
+#endif
+
+#define TCP_DEBUG 1
+#define FASTRETRANS_DEBUG 1
+
+/* Cancel timers, when they are not required. */
+#undef TCP_CLEAR_TIMERS
+
+#if 0
+#include <linux/config.h>
+#include <linux/tcp.h>
+#include <linux/slab.h>
+#include <linux/cache.h>
+#include <net/checksum.h>
+#include <net/sock.h>
+#else
+#include "linux.h"
+#endif
+
+/* This is for all connections with a full identity, no wildcards.
+ * New scheme, half the table is for TIME_WAIT, the other half is
+ * for the rest. I'll experiment with dynamic table growth later.
+ */
+struct tcp_ehash_bucket {
+ rwlock_t lock;
+ struct sock *chain;
+} __attribute__((__aligned__(8)));
+
+/* This is for listening sockets, thus all sockets which possess wildcards. */
+#define TCP_LHTABLE_SIZE 32 /* Yes, really, this is all you need. */
+
+/* There are a few simple rules, which allow for local port reuse by
+ * an application. In essence:
+ *
+ * 1) Sockets bound to different interfaces may share a local port.
+ * Failing that, goto test 2.
+ * 2) If all sockets have sk->reuse set, and none of them are in
+ * TCP_LISTEN state, the port may be shared.
+ * Failing that, goto test 3.
+ * 3) If all sockets are bound to a specific sk->rcv_saddr local
+ * address, and none of them are the same, the port may be
+ * shared.
+ * Failing this, the port cannot be shared.
+ *
+ * The interesting point, is test #2. This is what an FTP server does
+ * all day. To optimize this case we use a specific flag bit defined
+ * below. As we add sockets to a bind bucket list, we perform a
+ * check of: (newsk->reuse && (newsk->state != TCP_LISTEN))
+ * As long as all sockets added to a bind bucket pass this test,
+ * the flag bit will be set.
+ * The resulting situation is that tcp_v[46]_verify_bind() can just check
+ * for this flag bit, if it is set and the socket trying to bind has
+ * sk->reuse set, we don't even have to walk the owners list at all,
+ * we return that it is ok to bind this socket to the requested local port.
+ *
+ * Sounds like a lot of work, but it is worth it. In a more naive
+ * implementation (ie. current FreeBSD etc.) the entire list of ports
+ * must be walked for each data port opened by an ftp server. Needless
+ * to say, this does not scale at all. With a couple thousand FTP
+ * users logged onto your box, isn't it nice to know that new data
+ * ports are created in O(1) time? I thought so. ;-) -DaveM
+ */
+struct tcp_bind_bucket {
+ unsigned short port;
+ signed short fastreuse;
+ struct tcp_bind_bucket *next;
+ struct sock *owners;
+ struct tcp_bind_bucket **pprev;
+};
+
+struct tcp_bind_hashbucket {
+ spinlock_t lock;
+ struct tcp_bind_bucket *chain;
+};
+
+extern struct tcp_hashinfo {
+ /* This is for sockets with full identity only. Sockets here will
+ * always be without wildcards and will have the following invariant:
+ *
+ * TCP_ESTABLISHED <= sk->state < TCP_CLOSE
+ *
+ * First half of the table is for sockets not in TIME_WAIT, second half
+ * is for TIME_WAIT sockets only.
+ */
+ struct tcp_ehash_bucket *__tcp_ehash;
+
+ /* Ok, let's try this, I give up, we do need a local binding
+ * TCP hash as well as the others for fast bind/connect.
+ */
+ struct tcp_bind_hashbucket *__tcp_bhash;
+
+ int __tcp_bhash_size;
+ int __tcp_ehash_size;
+
+ /* All sockets in TCP_LISTEN state will be in here. This is the only
+ * table where wildcard'd TCP sockets can exist. Hash function here
+ * is just local port number.
+ */
+ struct sock *__tcp_listening_hash[TCP_LHTABLE_SIZE];
+
+ /* All the above members are written once at bootup and
+ * never written again _or_ are predominantly read-access.
+ *
+ * Now align to a new cache line as all the following members
+ * are often dirty.
+ */
+ rwlock_t __tcp_lhash_lock ____cacheline_aligned;
+ atomic_t __tcp_lhash_users;
+ wait_queue_head_t __tcp_lhash_wait;
+ spinlock_t __tcp_portalloc_lock;
+} tcp_hashinfo;
+
+#define tcp_ehash (tcp_hashinfo.__tcp_ehash)
+#define tcp_bhash (tcp_hashinfo.__tcp_bhash)
+#define tcp_ehash_size (tcp_hashinfo.__tcp_ehash_size)
+#define tcp_bhash_size (tcp_hashinfo.__tcp_bhash_size)
+#define tcp_listening_hash (tcp_hashinfo.__tcp_listening_hash)
+#define tcp_lhash_lock (tcp_hashinfo.__tcp_lhash_lock)
+#define tcp_lhash_users (tcp_hashinfo.__tcp_lhash_users)
+#define tcp_lhash_wait (tcp_hashinfo.__tcp_lhash_wait)
+#define tcp_portalloc_lock (tcp_hashinfo.__tcp_portalloc_lock)
+
+extern kmem_cache_t *tcp_bucket_cachep;
+extern struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *head,
+ unsigned short snum);
+extern void tcp_bucket_unlock(struct sock *sk);
+extern int tcp_port_rover;
+extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
+
+/* These are AF independent. */
+static __inline__ int tcp_bhashfn(__u16 lport)
+{
+ return (lport & (tcp_bhash_size - 1));
+}
+
+/* This is a TIME_WAIT bucket. It works around the memory consumption
+ * problems of sockets in such a state on heavily loaded servers, but
+ * without violating the protocol specification.
+ */
+struct tcp_tw_bucket {
+ /* These _must_ match the beginning of struct sock precisely.
+ * XXX Yes I know this is gross, but I'd have to edit every single
+ * XXX networking file if I created a "struct sock_header". -DaveM
+ */
+ __u32 daddr;
+ __u32 rcv_saddr;
+ __u16 dport;
+ unsigned short num;
+ int bound_dev_if;
+ struct sock *next;
+ struct sock **pprev;
+ struct sock *bind_next;
+ struct sock **bind_pprev;
+ unsigned char state,
+ substate; /* "zapped" is replaced with "substate" */
+ __u16 sport;
+ unsigned short family;
+ unsigned char reuse,
+ rcv_wscale; /* It is also TW bucket specific */
+ atomic_t refcnt;
+
+ /* And these are ours. */
+ int hashent;
+ int timeout;
+ __u32 rcv_nxt;
+ __u32 snd_nxt;
+ __u32 rcv_wnd;
+ __u32 ts_recent;
+ long ts_recent_stamp;
+ unsigned long ttd;
+ struct tcp_bind_bucket *tb;
+ struct tcp_tw_bucket *next_death;
+ struct tcp_tw_bucket **pprev_death;
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ struct in6_addr v6_daddr;
+ struct in6_addr v6_rcv_saddr;
+#endif
+};
+
+extern kmem_cache_t *tcp_timewait_cachep;
+
+static inline void tcp_tw_put(struct tcp_tw_bucket *tw)
+{
+ if (atomic_dec_and_test(&tw->refcnt)) {
+#ifdef INET_REFCNT_DEBUG
+ printk(KERN_DEBUG "tw_bucket %p released\n", tw);
+#endif
+ kmem_cache_free(tcp_timewait_cachep, tw);
+ }
+}
+
+extern atomic_t tcp_orphan_count;
+extern int tcp_tw_count;
+extern void tcp_time_wait(struct sock *sk, int state, int timeo);
+extern void tcp_timewait_kill(struct tcp_tw_bucket *tw);
+extern void tcp_tw_schedule(struct tcp_tw_bucket *tw, int timeo);
+extern void tcp_tw_deschedule(struct tcp_tw_bucket *tw);
+
+
+/* Socket demux engine toys. */
+#ifdef __BIG_ENDIAN
+#define TCP_COMBINED_PORTS(__sport, __dport) \
+ (((__u32)(__sport)<<16) | (__u32)(__dport))
+#else /* __LITTLE_ENDIAN */
+#define TCP_COMBINED_PORTS(__sport, __dport) \
+ (((__u32)(__dport)<<16) | (__u32)(__sport))
+#endif
+
+#if (BITS_PER_LONG == 64)
+#ifdef __BIG_ENDIAN
+#define TCP_V4_ADDR_COOKIE(__name, __saddr, __daddr) \
+ __u64 __name = (((__u64)(__saddr))<<32)|((__u64)(__daddr));
+#else /* __LITTLE_ENDIAN */
+#define TCP_V4_ADDR_COOKIE(__name, __saddr, __daddr) \
+ __u64 __name = (((__u64)(__daddr))<<32)|((__u64)(__saddr));
+#endif /* __BIG_ENDIAN */
+#define TCP_IPV4_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\
+ (((*((__u64 *)&((__sk)->daddr)))== (__cookie)) && \
+ ((*((__u32 *)&((__sk)->dport)))== (__ports)) && \
+ (!((__sk)->bound_dev_if) || ((__sk)->bound_dev_if == (__dif))))
+#else /* 32-bit arch */
+#define TCP_V4_ADDR_COOKIE(__name, __saddr, __daddr)
+#define TCP_IPV4_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\
+ (((__sk)->daddr == (__saddr)) && \
+ ((__sk)->rcv_saddr == (__daddr)) && \
+ ((*((__u32 *)&((__sk)->dport)))== (__ports)) && \
+ (!((__sk)->bound_dev_if) || ((__sk)->bound_dev_if == (__dif))))
+#endif /* 64-bit arch */
+
+#define TCP_IPV6_MATCH(__sk, __saddr, __daddr, __ports, __dif) \
+ (((*((__u32 *)&((__sk)->dport)))== (__ports)) && \
+ ((__sk)->family == AF_INET6) && \
+ !ipv6_addr_cmp(&(__sk)->net_pinfo.af_inet6.daddr, (__saddr)) && \
+ !ipv6_addr_cmp(&(__sk)->net_pinfo.af_inet6.rcv_saddr, (__daddr)) && \
+ (!((__sk)->bound_dev_if) || ((__sk)->bound_dev_if == (__dif))))
+
+/* These can have wildcards, don't try too hard. */
+static __inline__ int tcp_lhashfn(unsigned short num)
+{
+#if 0
+ return num & (TCP_LHTABLE_SIZE - 1);
+#else
+ return 0;
+#endif
+}
+
+static __inline__ int tcp_sk_listen_hashfn(struct sock *sk)
+{
+#if 0
+ return tcp_lhashfn(sk->num);
+#else
+ return 0;
+#endif
+}
+
+#define MAX_TCP_HEADER (128 + MAX_HEADER)
+
+/*
+ * Never offer a window over 32767 without using window scaling. Some
+ * poor stacks do signed 16bit maths!
+ */
+#define MAX_TCP_WINDOW 32767U
+
+/* Minimal accepted MSS. It is (60+60+8) - (20+20). */
+#define TCP_MIN_MSS 88U
+
+/* Minimal RCV_MSS. */
+#define TCP_MIN_RCVMSS 536U
+
+/* After receiving this amount of duplicate ACKs fast retransmit starts. */
+#define TCP_FASTRETRANS_THRESH 3
+
+/* Maximal reordering. */
+#define TCP_MAX_REORDERING 127
+
+/* Maximal number of ACKs sent quickly to accelerate slow-start. */
+#define TCP_MAX_QUICKACKS 16U
+
+/* urg_data states */
+#define TCP_URG_VALID 0x0100
+#define TCP_URG_NOTYET 0x0200
+#define TCP_URG_READ 0x0400
+
+#define TCP_RETR1 3 /*
+ * This is how many retries it does before it
+ * tries to figure out if the gateway is
+ * down. Minimal RFC value is 3; it corresponds
+ * to ~3sec-8min depending on RTO.
+ */
+
+#define TCP_RETR2 15 /*
+ * This should take at least
+ * 90 minutes to time out.
+ * RFC1122 says that the limit is 100 sec.
+ * 15 is ~13-30min depending on RTO.
+ */
+
+#define TCP_SYN_RETRIES 5 /* number of times to retry active opening a
+ * connection: ~180sec is RFC minumum */
+
+#define TCP_SYNACK_RETRIES 5 /* number of times to retry passive opening a
+ * connection: ~180sec is RFC minumum */
+
+
+#define TCP_ORPHAN_RETRIES 7 /* number of times to retry on an orphaned
+ * socket. 7 is ~50sec-16min.
+ */
+
+
+#define TCP_TIMEWAIT_LEN (60*1000)
+//#define TCP_TIMEWAIT_LEN (60*HZ)
+/* how long to wait to destroy TIME-WAIT
+ * state, about 60 seconds */
+#define TCP_FIN_TIMEOUT TCP_TIMEWAIT_LEN
+ /* BSD style FIN_WAIT2 deadlock breaker.
+ * It used to be 3min, new value is 60sec,
+ * to combine FIN-WAIT-2 timeout with
+ * TIME-WAIT timer.
+ */
+
+#define TCP_DELACK_MAX ((unsigned)(HZ/5)) /* maximal time to delay before sending an ACK */
+#if HZ >= 100
+#define TCP_DELACK_MIN ((unsigned)(HZ/25)) /* minimal time to delay before sending an ACK */
+#define TCP_ATO_MIN ((unsigned)(HZ/25))
+#else
+#define TCP_DELACK_MIN 4U
+#define TCP_ATO_MIN 4U
+#endif
+#define TCP_RTO_MAX ((unsigned)(120*HZ))
+#define TCP_RTO_MIN ((unsigned)(HZ/5))
+#define TCP_TIMEOUT_INIT ((unsigned)(3*HZ)) /* RFC 1122 initial RTO value */
+
+#define TCP_RESOURCE_PROBE_INTERVAL ((unsigned)(HZ/2U)) /* Maximal interval between probes
+ * for local resources.
+ */
+
+#define TCP_KEEPALIVE_TIME (120*60*HZ) /* two hours */
+#define TCP_KEEPALIVE_PROBES 9 /* Max of 9 keepalive probes */
+#define TCP_KEEPALIVE_INTVL (75*HZ)
+
+#define MAX_TCP_KEEPIDLE 32767
+#define MAX_TCP_KEEPINTVL 32767
+#define MAX_TCP_KEEPCNT 127
+#define MAX_TCP_SYNCNT 127
+
+/* TIME_WAIT reaping mechanism. */
+#define TCP_TWKILL_SLOTS 8 /* Please keep this a power of 2. */
+#define TCP_TWKILL_PERIOD (TCP_TIMEWAIT_LEN/TCP_TWKILL_SLOTS)
+
+#define TCP_SYNQ_INTERVAL (HZ/5) /* Period of SYNACK timer */
+#define TCP_SYNQ_HSIZE 512 /* Size of SYNACK hash table */
+
+#define TCP_PAWS_24DAYS (60 * 60 * 24 * 24)
+#define TCP_PAWS_MSL 60 /* Per-host timestamps are invalidated
+ * after this time. It should be equal
+ * (or greater than) TCP_TIMEWAIT_LEN
+ * to provide reliability equal to one
+ * provided by timewait state.
+ */
+#define TCP_PAWS_WINDOW 1 /* Replay window for per-host
+ * timestamps. It must be less than
+ * minimal timewait lifetime.
+ */
+
+#define TCP_TW_RECYCLE_SLOTS_LOG 5
+#define TCP_TW_RECYCLE_SLOTS (1<<TCP_TW_RECYCLE_SLOTS_LOG)
+
+/* If time > 4sec, it is "slow" path, no recycling is required,
+ so that we select tick to get range about 4 seconds.
+ */
+
+#if 0
+#if HZ <= 16 || HZ > 4096
+# error Unsupported: HZ <= 16 or HZ > 4096
+#elif HZ <= 32
+# define TCP_TW_RECYCLE_TICK (5+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#elif HZ <= 64
+# define TCP_TW_RECYCLE_TICK (6+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#elif HZ <= 128
+# define TCP_TW_RECYCLE_TICK (7+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#elif HZ <= 256
+# define TCP_TW_RECYCLE_TICK (8+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#elif HZ <= 512
+# define TCP_TW_RECYCLE_TICK (9+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#elif HZ <= 1024
+# define TCP_TW_RECYCLE_TICK (10+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#elif HZ <= 2048
+# define TCP_TW_RECYCLE_TICK (11+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#else
+# define TCP_TW_RECYCLE_TICK (12+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#endif
+#else
+#define TCP_TW_RECYCLE_TICK (0)
+#endif
+
+/*
+ * TCP option
+ */
+
+#define TCPOPT_NOP 1 /* Padding */
+#define TCPOPT_EOL 0 /* End of options */
+#define TCPOPT_MSS 2 /* Segment size negotiating */
+#define TCPOPT_WINDOW 3 /* Window scaling */
+#define TCPOPT_SACK_PERM 4 /* SACK Permitted */
+#define TCPOPT_SACK 5 /* SACK Block */
+#define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
+
+/*
+ * TCP option lengths
+ */
+
+#define TCPOLEN_MSS 4
+#define TCPOLEN_WINDOW 3
+#define TCPOLEN_SACK_PERM 2
+#define TCPOLEN_TIMESTAMP 10
+
+/* But this is what stacks really send out. */
+#define TCPOLEN_TSTAMP_ALIGNED 12
+#define TCPOLEN_WSCALE_ALIGNED 4
+#define TCPOLEN_SACKPERM_ALIGNED 4
+#define TCPOLEN_SACK_BASE 2
+#define TCPOLEN_SACK_BASE_ALIGNED 4
+#define TCPOLEN_SACK_PERBLOCK 8
+
+#define TCP_TIME_RETRANS 1 /* Retransmit timer */
+#define TCP_TIME_DACK 2 /* Delayed ack timer */
+#define TCP_TIME_PROBE0 3 /* Zero window probe timer */
+#define TCP_TIME_KEEPOPEN 4 /* Keepalive timer */
+
+#if 0
+/* sysctl variables for tcp */
+extern int sysctl_max_syn_backlog;
+extern int sysctl_tcp_timestamps;
+extern int sysctl_tcp_window_scaling;
+extern int sysctl_tcp_sack;
+extern int sysctl_tcp_fin_timeout;
+extern int sysctl_tcp_tw_recycle;
+extern int sysctl_tcp_keepalive_time;
+extern int sysctl_tcp_keepalive_probes;
+extern int sysctl_tcp_keepalive_intvl;
+extern int sysctl_tcp_syn_retries;
+extern int sysctl_tcp_synack_retries;
+extern int sysctl_tcp_retries1;
+extern int sysctl_tcp_retries2;
+extern int sysctl_tcp_orphan_retries;
+extern int sysctl_tcp_syncookies;
+extern int sysctl_tcp_retrans_collapse;
+extern int sysctl_tcp_stdurg;
+extern int sysctl_tcp_rfc1337;
+extern int sysctl_tcp_abort_on_overflow;
+extern int sysctl_tcp_max_orphans;
+extern int sysctl_tcp_max_tw_buckets;
+extern int sysctl_tcp_fack;
+extern int sysctl_tcp_reordering;
+extern int sysctl_tcp_ecn;
+extern int sysctl_tcp_dsack;
+extern int sysctl_tcp_mem[3];
+extern int sysctl_tcp_wmem[3];
+extern int sysctl_tcp_rmem[3];
+extern int sysctl_tcp_app_win;
+extern int sysctl_tcp_adv_win_scale;
+extern int sysctl_tcp_tw_reuse;
+#endif
+
+extern atomic_t tcp_memory_allocated;
+extern atomic_t tcp_sockets_allocated;
+extern int tcp_memory_pressure;
+
+struct open_request;
+
+struct or_calltable {
+ int family;
+ int (*rtx_syn_ack) (struct sock *sk, struct open_request *req, struct dst_entry*);
+ void (*send_ack) (struct sk_buff *skb, struct open_request *req);
+ void (*destructor) (struct open_request *req);
+ void (*send_reset) (struct sk_buff *skb);
+};
+
+struct tcp_v4_open_req {
+ __u32 loc_addr;
+ __u32 rmt_addr;
+ struct ip_options *opt;
+};
+
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+struct tcp_v6_open_req {
+ struct in6_addr loc_addr;
+ struct in6_addr rmt_addr;
+ struct sk_buff *pktopts;
+ int iif;
+};
+#endif
+
+/* this structure is too big */
+struct open_request {
+ struct open_request *dl_next; /* Must be first member! */
+ __u32 rcv_isn;
+ __u32 snt_isn;
+ __u16 rmt_port;
+ __u16 mss;
+ __u8 retrans;
+ __u8 __pad;
+ __u16 snd_wscale : 4,
+ rcv_wscale : 4,
+ tstamp_ok : 1,
+ sack_ok : 1,
+ wscale_ok : 1,
+ ecn_ok : 1,
+ acked : 1;
+ /* The following two fields can be easily recomputed I think -AK */
+ __u32 window_clamp; /* window clamp at creation time */
+ __u32 rcv_wnd; /* rcv_wnd offered first time */
+ __u32 ts_recent;
+ unsigned long expires;
+ struct or_calltable *class;
+ struct sock *sk;
+ union {
+ struct tcp_v4_open_req v4_req;
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ struct tcp_v6_open_req v6_req;
+#endif
+ } af;
+};
+
+/* SLAB cache for open requests. */
+extern kmem_cache_t *tcp_openreq_cachep;
+
+#define tcp_openreq_alloc() kmem_cache_alloc(tcp_openreq_cachep, SLAB_ATOMIC)
+#define tcp_openreq_fastfree(req) kmem_cache_free(tcp_openreq_cachep, req)
+
+static inline void tcp_openreq_free(struct open_request *req)
+{
+ req->class->destructor(req);
+ tcp_openreq_fastfree(req);
+}
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#define TCP_INET_FAMILY(fam) ((fam) == AF_INET)
+#else
+#define TCP_INET_FAMILY(fam) 1
+#endif
+
+/*
+ * Pointers to address related TCP functions
+ * (i.e. things that depend on the address family)
+ *
+ * BUGGG_FUTURE: all the idea behind this struct is wrong.
+ * It mixes socket frontend with transport function.
+ * With port sharing between IPv6/v4 it gives the only advantage,
+ * only poor IPv6 needs to permanently recheck, that it
+ * is still IPv6 8)8) It must be cleaned up as soon as possible.
+ * --ANK (980802)
+ */
+
+struct tcp_func {
+ int (*queue_xmit) (struct sk_buff *skb);
+
+ void (*send_check) (struct sock *sk,
+ struct tcphdr *th,
+ int len,
+ struct sk_buff *skb);
+
+ int (*rebuild_header) (struct sock *sk);
+
+ int (*conn_request) (struct sock *sk,
+ struct sk_buff *skb);
+
+ struct sock * (*syn_recv_sock) (struct sock *sk,
+ struct sk_buff *skb,
+ struct open_request *req,
+ struct dst_entry *dst);
+
+ int (*remember_stamp) (struct sock *sk);
+
+ __u16 net_header_len;
+
+ int (*setsockopt) (struct sock *sk,
+ int level,
+ int optname,
+ char *optval,
+ int optlen);
+
+ int (*getsockopt) (struct sock *sk,
+ int level,
+ int optname,
+ char *optval,
+ int *optlen);
+
+
+ void (*addr2sockaddr) (struct sock *sk,
+ struct sockaddr *);
+
+ int sockaddr_len;
+};
+
+/*
+ * The next routines deal with comparing 32 bit unsigned ints
+ * and worry about wraparound (automatic with unsigned arithmetic).
+ */
+
+extern __inline int before(__u32 seq1, __u32 seq2)
+{
+ return (__s32)(seq1-seq2) < 0;
+}
+
+extern __inline int after(__u32 seq1, __u32 seq2)
+{
+ return (__s32)(seq2-seq1) < 0;
+}
+
+
+/* is s2<=s1<=s3 ? */
+extern __inline int between(__u32 seq1, __u32 seq2, __u32 seq3)
+{
+ return seq3 - seq2 >= seq1 - seq2;
+}
+
+
+extern struct proto tcp_prot;
+
+#ifdef ROS_STATISTICS
+extern struct tcp_mib tcp_statistics[NR_CPUS*2];
+
+#define TCP_INC_STATS(field) SNMP_INC_STATS(tcp_statistics, field)
+#define TCP_INC_STATS_BH(field) SNMP_INC_STATS_BH(tcp_statistics, field)
+#define TCP_INC_STATS_USER(field) SNMP_INC_STATS_USER(tcp_statistics, field)
+#endif
+
+extern void tcp_put_port(struct sock *sk);
+extern void __tcp_put_port(struct sock *sk);
+extern void tcp_inherit_port(struct sock *sk, struct sock *child);
+
+extern void tcp_v4_err(struct sk_buff *skb, u32);
+
+extern void tcp_shutdown (struct sock *sk, int how);
+
+extern int tcp_v4_rcv(struct sk_buff *skb);
+
+extern int tcp_v4_remember_stamp(struct sock *sk);
+
+extern int tcp_v4_tw_remember_stamp(struct tcp_tw_bucket *tw);
+
+extern int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size);
+extern ssize_t tcp_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags);
+
+extern int tcp_ioctl(struct sock *sk,
+ int cmd,
+ unsigned long arg);
+
+extern int tcp_rcv_state_process(struct sock *sk,
+ struct sk_buff *skb,
+ struct tcphdr *th,
+ unsigned len);
+
+extern int tcp_rcv_established(struct sock *sk,
+ struct sk_buff *skb,
+ struct tcphdr *th,
+ unsigned len);
+
+enum tcp_ack_state_t
+{
+ TCP_ACK_SCHED = 1,
+ TCP_ACK_TIMER = 2,
+ TCP_ACK_PUSHED= 4
+};
+
+static inline void tcp_schedule_ack(struct tcp_opt *tp)
+{
+ tp->ack.pending |= TCP_ACK_SCHED;
+}
+
+static inline int tcp_ack_scheduled(struct tcp_opt *tp)
+{
+ return tp->ack.pending&TCP_ACK_SCHED;
+}
+
+static __inline__ void tcp_dec_quickack_mode(struct tcp_opt *tp)
+{
+ if (tp->ack.quick && --tp->ack.quick == 0) {
+ /* Leaving quickack mode we deflate ATO. */
+ tp->ack.ato = TCP_ATO_MIN;
+ }
+}
+
+extern void tcp_enter_quickack_mode(struct tcp_opt *tp);
+
+static __inline__ void tcp_delack_init(struct tcp_opt *tp)
+{
+ memset(&tp->ack, 0, sizeof(tp->ack));
+}
+
+static inline void tcp_clear_options(struct tcp_opt *tp)
+{
+ tp->tstamp_ok = tp->sack_ok = tp->wscale_ok = tp->snd_wscale = 0;
+}
+
+enum tcp_tw_status
+{
+ TCP_TW_SUCCESS = 0,
+ TCP_TW_RST = 1,
+ TCP_TW_ACK = 2,
+ TCP_TW_SYN = 3
+};
+
+
+extern enum tcp_tw_status tcp_timewait_state_process(struct tcp_tw_bucket *tw,
+ struct sk_buff *skb,
+ struct tcphdr *th,
+ unsigned len);
+
+extern struct sock * tcp_check_req(struct sock *sk,struct sk_buff *skb,
+ struct open_request *req,
+ struct open_request **prev);
+extern int tcp_child_process(struct sock *parent,
+ struct sock *child,
+ struct sk_buff *skb);
+extern void tcp_enter_loss(struct sock *sk, int how);
+extern void tcp_clear_retrans(struct tcp_opt *tp);
+extern void tcp_update_metrics(struct sock *sk);
+
+extern void tcp_close(struct sock *sk,
+ long timeout);
+extern struct sock * tcp_accept(struct sock *sk, int flags, int *err);
+extern unsigned int tcp_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait);
+extern void tcp_write_space(struct sock *sk);
+
+extern int tcp_getsockopt(struct sock *sk, int level,
+ int optname, char *optval,
+ int *optlen);
+extern int tcp_setsockopt(struct sock *sk, int level,
+ int optname, char *optval,
+ int optlen);
+extern void tcp_set_keepalive(struct sock *sk, int val);
+extern int tcp_recvmsg(struct sock *sk,
+ struct msghdr *msg,
+ int len, int nonblock,
+ int flags, int *addr_len);
+
+extern int tcp_listen_start(struct sock *sk);
+
+extern void tcp_parse_options(struct sk_buff *skb,
+ struct tcp_opt *tp,
+ int estab);
+
+/*
+ * TCP v4 functions exported for the inet6 API
+ */
+
+extern int tcp_v4_rebuild_header(struct sock *sk);
+
+extern int tcp_v4_build_header(struct sock *sk,
+ struct sk_buff *skb);
+
+extern void tcp_v4_send_check(struct sock *sk,
+ struct tcphdr *th, int len,
+ struct sk_buff *skb);
+
+extern int tcp_v4_conn_request(struct sock *sk,
+ struct sk_buff *skb);
+
+extern struct sock * tcp_create_openreq_child(struct sock *sk,
+ struct open_request *req,
+ struct sk_buff *skb);
+
+extern struct sock * tcp_v4_syn_recv_sock(struct sock *sk,
+ struct sk_buff *skb,
+ struct open_request *req,
+ struct dst_entry *dst);
+
+extern int tcp_v4_do_rcv(struct sock *sk,
+ struct sk_buff *skb);
+
+extern int tcp_v4_connect(struct sock *sk,
+ struct sockaddr *uaddr,
+ int addr_len);
+
+extern int tcp_connect(struct sock *sk);
+
+extern struct sk_buff * tcp_make_synack(struct sock *sk,
+ struct dst_entry *dst,
+ struct open_request *req);
+
+extern int tcp_disconnect(struct sock *sk, int flags);
+
+extern void tcp_unhash(struct sock *sk);
+
+extern int tcp_v4_hash_connecting(struct sock *sk);
+
+
+/* From syncookies.c */
+extern struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+ struct ip_options *opt);
+extern __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb,
+ __u16 *mss);
+
+/* tcp_output.c */
+
+extern int tcp_write_xmit(struct sock *, int nonagle);
+extern int tcp_retransmit_skb(struct sock *, struct sk_buff *);
+extern void tcp_xmit_retransmit_queue(struct sock *);
+extern void tcp_simple_retransmit(struct sock *);
+
+extern void tcp_send_probe0(struct sock *);
+extern void tcp_send_partial(struct sock *);
+extern int tcp_write_wakeup(struct sock *);
+extern void tcp_send_fin(struct sock *sk);
+extern void tcp_send_active_reset(struct sock *sk, int priority);
+extern int tcp_send_synack(struct sock *);
+extern int tcp_transmit_skb(struct sock *, struct sk_buff *);
+extern void tcp_send_skb(struct sock *, struct sk_buff *, int force_queue, unsigned mss_now);
+extern void tcp_push_one(struct sock *, unsigned mss_now);
+extern void tcp_send_ack(struct sock *sk);
+extern void tcp_send_delayed_ack(struct sock *sk);
+
+/* tcp_timer.c */
+extern void tcp_init_xmit_timers(struct sock *);
+extern void tcp_clear_xmit_timers(struct sock *);
+
+extern void tcp_delete_keepalive_timer (struct sock *);
+extern void tcp_reset_keepalive_timer (struct sock *, unsigned long);
+extern int tcp_sync_mss(struct sock *sk, u32 pmtu);
+
+extern const char timer_bug_msg[];
+
+/* Read 'sendfile()'-style from a TCP socket */
+typedef int (*sk_read_actor_t)(read_descriptor_t *, struct sk_buff *,
+ unsigned int, size_t);
+extern int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
+ sk_read_actor_t recv_actor);
+
+static inline void tcp_clear_xmit_timer(struct sock *sk, int what)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ switch (what) {
+ case TCP_TIME_RETRANS:
+ case TCP_TIME_PROBE0:
+ tp->pending = 0;
+
+#ifdef TCP_CLEAR_TIMERS
+ if (timer_pending(&tp->retransmit_timer) &&
+ del_timer(&tp->retransmit_timer))
+ __sock_put(sk);
+#endif
+ break;
+ case TCP_TIME_DACK:
+ tp->ack.blocked = 0;
+ tp->ack.pending = 0;
+
+#ifdef TCP_CLEAR_TIMERS
+ if (timer_pending(&tp->delack_timer) &&
+ del_timer(&tp->delack_timer))
+ __sock_put(sk);
+#endif
+ break;
+ default:
+ printk(timer_bug_msg);
+ return;
+ };
+#endif
+}
+
+/*
+ * Reset the retransmission timer
+ */
+static inline void tcp_reset_xmit_timer(struct sock *sk, int what, unsigned long when)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ if (when > TCP_RTO_MAX) {
+#ifdef TCP_DEBUG
+ printk(KERN_DEBUG "reset_xmit_timer sk=%p %d when=0x%lx, caller=%p\n", sk, what, when, current_text_addr());
+#endif
+ when = TCP_RTO_MAX;
+ }
+
+ switch (what) {
+ case TCP_TIME_RETRANS:
+ case TCP_TIME_PROBE0:
+ tp->pending = what;
+ tp->timeout = jiffies+when;
+ if (!mod_timer(&tp->retransmit_timer, tp->timeout))
+ sock_hold(sk);
+ break;
+
+ case TCP_TIME_DACK:
+ tp->ack.pending |= TCP_ACK_TIMER;
+ tp->ack.timeout = jiffies+when;
+ if (!mod_timer(&tp->delack_timer, tp->ack.timeout))
+ sock_hold(sk);
+ break;
+
+ default:
+ printk(KERN_DEBUG "bug: unknown timer value\n");
+ };
+#endif
+}
+
+/* Compute the current effective MSS, taking SACKs and IP options,
+ * and even PMTU discovery events into account.
+ */
+
+static __inline__ unsigned int tcp_current_mss(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ struct dst_entry *dst = __sk_dst_get(sk);
+ int mss_now = tp->mss_cache;
+
+ if (dst && dst->pmtu != tp->pmtu_cookie)
+ mss_now = tcp_sync_mss(sk, dst->pmtu);
+
+ if (tp->eff_sacks)
+ mss_now -= (TCPOLEN_SACK_BASE_ALIGNED +
+ (tp->eff_sacks * TCPOLEN_SACK_PERBLOCK));
+ return mss_now;
+#else
+ return 0;
+#endif
+}
+
+/* Initialize RCV_MSS value.
+ * RCV_MSS is an our guess about MSS used by the peer.
+ * We haven't any direct information about the MSS.
+ * It's better to underestimate the RCV_MSS rather than overestimate.
+ * Overestimations make us ACKing less frequently than needed.
+ * Underestimations are more easy to detect and fix by tcp_measure_rcv_mss().
+ */
+
+static inline void tcp_initialize_rcv_mss(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ unsigned int hint = min(tp->advmss, tp->mss_cache);
+
+ hint = min(hint, tp->rcv_wnd/2);
+ hint = min(hint, TCP_MIN_RCVMSS);
+ hint = max(hint, TCP_MIN_MSS);
+
+ tp->ack.rcv_mss = hint;
+#endif
+}
+
+static __inline__ void __tcp_fast_path_on(struct tcp_opt *tp, u32 snd_wnd)
+{
+#if 0
+ tp->pred_flags = htonl((tp->tcp_header_len << 26) |
+ ntohl(TCP_FLAG_ACK) |
+ snd_wnd);
+#endif
+}
+
+static __inline__ void tcp_fast_path_on(struct tcp_opt *tp)
+{
+#if 0
+ __tcp_fast_path_on(tp, tp->snd_wnd>>tp->snd_wscale);
+#endif
+}
+
+static inline void tcp_fast_path_check(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+ if (skb_queue_len(&tp->out_of_order_queue) == 0 &&
+ tp->rcv_wnd &&
+ atomic_read(&sk->rmem_alloc) < sk->rcvbuf &&
+ !tp->urg_data)
+ tcp_fast_path_on(tp);
+#endif
+}
+
+/* Compute the actual receive window we are currently advertising.
+ * Rcv_nxt can be after the window if our peer push more data
+ * than the offered window.
+ */
+static __inline__ u32 tcp_receive_window(struct tcp_opt *tp)
+{
+#if 0
+ s32 win = tp->rcv_wup + tp->rcv_wnd - tp->rcv_nxt;
+
+ if (win < 0)
+ win = 0;
+ return (u32) win;
+#else
+ return 0;
+#endif
+}
+
+/* Choose a new window, without checks for shrinking, and without
+ * scaling applied to the result. The caller does these things
+ * if necessary. This is a "raw" window selection.
+ */
+extern u32 __tcp_select_window(struct sock *sk);
+
+/* TCP timestamps are only 32-bits, this causes a slight
+ * complication on 64-bit systems since we store a snapshot
+ * of jiffies in the buffer control blocks below. We decidely
+ * only use of the low 32-bits of jiffies and hide the ugly
+ * casts with the following macro.
+ */
+#define tcp_time_stamp ((__u32)(jiffies))
+
+/* This is what the send packet queueing engine uses to pass
+ * TCP per-packet control information to the transmission
+ * code. We also store the host-order sequence numbers in
+ * here too. This is 36 bytes on 32-bit architectures,
+ * 40 bytes on 64-bit machines, if this grows please adjust
+ * skbuff.h:skbuff->cb[xxx] size appropriately.
+ */
+struct tcp_skb_cb {
+ union {
+#if 0
+ struct inet_skb_parm h4;
+#endif
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ struct inet6_skb_parm h6;
+#endif
+ } header; /* For incoming frames */
+ __u32 seq; /* Starting sequence number */
+ __u32 end_seq; /* SEQ + FIN + SYN + datalen */
+ __u32 when; /* used to compute rtt's */
+ __u8 flags; /* TCP header flags. */
+
+ /* NOTE: These must match up to the flags byte in a
+ * real TCP header.
+ */
+#define TCPCB_FLAG_FIN 0x01
+#define TCPCB_FLAG_SYN 0x02
+#define TCPCB_FLAG_RST 0x04
+#define TCPCB_FLAG_PSH 0x08
+#define TCPCB_FLAG_ACK 0x10
+#define TCPCB_FLAG_URG 0x20
+#define TCPCB_FLAG_ECE 0x40
+#define TCPCB_FLAG_CWR 0x80
+
+ __u8 sacked; /* State flags for SACK/FACK. */
+#define TCPCB_SACKED_ACKED 0x01 /* SKB ACK'd by a SACK block */
+#define TCPCB_SACKED_RETRANS 0x02 /* SKB retransmitted */
+#define TCPCB_LOST 0x04 /* SKB is lost */
+#define TCPCB_TAGBITS 0x07 /* All tag bits */
+
+#define TCPCB_EVER_RETRANS 0x80 /* Ever retransmitted frame */
+#define TCPCB_RETRANS (TCPCB_SACKED_RETRANS|TCPCB_EVER_RETRANS)
+
+#define TCPCB_URG 0x20 /* Urgent pointer advenced here */
+
+#define TCPCB_AT_TAIL (TCPCB_URG)
+
+ __u16 urg_ptr; /* Valid w/URG flags is set. */
+ __u32 ack_seq; /* Sequence number ACK'd */
+};
+
+#define TCP_SKB_CB(__skb) ((struct tcp_skb_cb *)&((__skb)->cb[0]))
+
+#define for_retrans_queue(skb, sk, tp) \
+ for (skb = (sk)->write_queue.next; \
+ (skb != (tp)->send_head) && \
+ (skb != (struct sk_buff *)&(sk)->write_queue); \
+ skb=skb->next)
+
+
+//#include <net/tcp_ecn.h>
+
+
+/*
+ * Compute minimal free write space needed to queue new packets.
+ */
+static inline int tcp_min_write_space(struct sock *sk)
+{
+#if 0
+ return sk->wmem_queued/2;
+#else
+return 0;
+#endif
+}
+
+static inline int tcp_wspace(struct sock *sk)
+{
+#if 0
+ return sk->sndbuf - sk->wmem_queued;
+#else
+return 0;
+#endif
+}
+
+
+/* This determines how many packets are "in the network" to the best
+ * of our knowledge. In many cases it is conservative, but where
+ * detailed information is available from the receiver (via SACK
+ * blocks etc.) we can make more aggressive calculations.
+ *
+ * Use this for decisions involving congestion control, use just
+ * tp->packets_out to determine if the send queue is empty or not.
+ *
+ * Read this equation as:
+ *
+ * "Packets sent once on transmission queue" MINUS
+ * "Packets left network, but not honestly ACKed yet" PLUS
+ * "Packets fast retransmitted"
+ */
+static __inline__ unsigned int tcp_packets_in_flight(struct tcp_opt *tp)
+{
+#if 0
+ return tp->packets_out - tp->left_out + tp->retrans_out;
+#else
+ return 0;
+#endif
+}
+
+/* Recalculate snd_ssthresh, we want to set it to:
+ *
+ * one half the current congestion window, but no
+ * less than two segments
+ */
+static inline __u32 tcp_recalc_ssthresh(struct tcp_opt *tp)
+{
+#if 0
+ return max(tp->snd_cwnd >> 1U, 2U);
+#else
+ return 0;
+#endif
+}
+
+/* If cwnd > ssthresh, we may raise ssthresh to be half-way to cwnd.
+ * The exception is rate halving phase, when cwnd is decreasing towards
+ * ssthresh.
+ */
+static inline __u32 tcp_current_ssthresh(struct tcp_opt *tp)
+{
+#if 0
+ if ((1<<tp->ca_state)&(TCPF_CA_CWR|TCPF_CA_Recovery))
+ return tp->snd_ssthresh;
+ else
+ return max(tp->snd_ssthresh,
+ ((tp->snd_cwnd >> 1) +
+ (tp->snd_cwnd >> 2)));
+#else
+ return 0;
+#endif
+}
+
+static inline void tcp_sync_left_out(struct tcp_opt *tp)
+{
+#if 0
+ if (tp->sack_ok && tp->sacked_out >= tp->packets_out - tp->lost_out)
+ tp->sacked_out = tp->packets_out - tp->lost_out;
+ tp->left_out = tp->sacked_out + tp->lost_out;
+#endif
+}
+
+extern void tcp_cwnd_application_limited(struct sock *sk);
+
+/* Congestion window validation. (RFC2861) */
+
+static inline void tcp_cwnd_validate(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+ if (tp->packets_out >= tp->snd_cwnd) {
+ /* Network is feed fully. */
+ tp->snd_cwnd_used = 0;
+ tp->snd_cwnd_stamp = tcp_time_stamp;
+ } else {
+ /* Network starves. */
+ if (tp->packets_out > tp->snd_cwnd_used)
+ tp->snd_cwnd_used = tp->packets_out;
+
+ if ((s32)(tcp_time_stamp - tp->snd_cwnd_stamp) >= tp->rto)
+ tcp_cwnd_application_limited(sk);
+ }
+#endif
+}
+
+/* Set slow start threshould and cwnd not falling to slow start */
+static inline void __tcp_enter_cwr(struct tcp_opt *tp)
+{
+#if 0
+ tp->undo_marker = 0;
+ tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
+ tp->snd_cwnd = min(tp->snd_cwnd,
+ tcp_packets_in_flight(tp) + 1U);
+ tp->snd_cwnd_cnt = 0;
+ tp->high_seq = tp->snd_nxt;
+ tp->snd_cwnd_stamp = tcp_time_stamp;
+ TCP_ECN_queue_cwr(tp);
+#endif
+}
+
+static inline void tcp_enter_cwr(struct tcp_opt *tp)
+{
+#if 0
+ tp->prior_ssthresh = 0;
+ if (tp->ca_state < TCP_CA_CWR) {
+ __tcp_enter_cwr(tp);
+ tp->ca_state = TCP_CA_CWR;
+ }
+#endif
+}
+
+extern __u32 tcp_init_cwnd(struct tcp_opt *tp);
+
+/* Slow start with delack produces 3 packets of burst, so that
+ * it is safe "de facto".
+ */
+static __inline__ __u32 tcp_max_burst(struct tcp_opt *tp)
+{
+ return 3;
+}
+
+static __inline__ int tcp_minshall_check(struct tcp_opt *tp)
+{
+#if 0
+ return after(tp->snd_sml,tp->snd_una) &&
+ !after(tp->snd_sml, tp->snd_nxt);
+#else
+ return 0;
+#endif
+}
+
+static __inline__ void tcp_minshall_update(struct tcp_opt *tp, int mss, struct sk_buff *skb)
+{
+#if 0
+ if (skb->len < mss)
+ tp->snd_sml = TCP_SKB_CB(skb)->end_seq;
+#endif
+}
+
+/* Return 0, if packet can be sent now without violation Nagle's rules:
+ 1. It is full sized.
+ 2. Or it contains FIN.
+ 3. Or TCP_NODELAY was set.
+ 4. Or TCP_CORK is not set, and all sent packets are ACKed.
+ With Minshall's modification: all sent small packets are ACKed.
+ */
+
+static __inline__ int
+tcp_nagle_check(struct tcp_opt *tp, struct sk_buff *skb, unsigned mss_now, int nonagle)
+{
+#if 0
+ return (skb->len < mss_now &&
+ !(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
+ (nonagle == 2 ||
+ (!nonagle &&
+ tp->packets_out &&
+ tcp_minshall_check(tp))));
+#else
+ return 0;
+#endif
+}
+
+/* This checks if the data bearing packet SKB (usually tp->send_head)
+ * should be put on the wire right now.
+ */
+static __inline__ int tcp_snd_test(struct tcp_opt *tp, struct sk_buff *skb,
+ unsigned cur_mss, int nonagle)
+{
+#if 0
+ /* RFC 1122 - section 4.2.3.4
+ *
+ * We must queue if
+ *
+ * a) The right edge of this frame exceeds the window
+ * b) There are packets in flight and we have a small segment
+ * [SWS avoidance and Nagle algorithm]
+ * (part of SWS is done on packetization)
+ * Minshall version sounds: there are no _small_
+ * segments in flight. (tcp_nagle_check)
+ * c) We have too many packets 'in flight'
+ *
+ * Don't use the nagle rule for urgent data (or
+ * for the final FIN -DaveM).
+ *
+ * Also, Nagle rule does not apply to frames, which
+ * sit in the middle of queue (they have no chances
+ * to get new data) and if room at tail of skb is
+ * not enough to save something seriously (<32 for now).
+ */
+
+ /* Don't be strict about the congestion window for the
+ * final FIN frame. -DaveM
+ */
+ return ((nonagle==1 || tp->urg_mode
+ || !tcp_nagle_check(tp, skb, cur_mss, nonagle)) &&
+ ((tcp_packets_in_flight(tp) < tp->snd_cwnd) ||
+ (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)) &&
+ !after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd));
+#else
+ return 0;
+#endif
+}
+
+static __inline__ void tcp_check_probe_timer(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+ if (!tp->packets_out && !tp->pending)
+ tcp_reset_xmit_timer(sk, TCP_TIME_PROBE0, tp->rto);
+#endif
+}
+
+static __inline__ int tcp_skb_is_last(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+ return (skb->next == (struct sk_buff*)&sk->write_queue);
+#else
+ return 0;
+#endif
+}
+
+/* Push out any pending frames which were held back due to
+ * TCP_CORK or attempt at coalescing tiny packets.
+ * The socket must be locked by the caller.
+ */
+static __inline__ void __tcp_push_pending_frames(struct sock *sk,
+ struct tcp_opt *tp,
+ unsigned cur_mss,
+ int nonagle)
+{
+#if 0
+ struct sk_buff *skb = tp->send_head;
+
+ if (skb) {
+ if (!tcp_skb_is_last(sk, skb))
+ nonagle = 1;
+ if (!tcp_snd_test(tp, skb, cur_mss, nonagle) ||
+ tcp_write_xmit(sk, nonagle))
+ tcp_check_probe_timer(sk, tp);
+ }
+ tcp_cwnd_validate(sk, tp);
+#endif
+}
+
+static __inline__ void tcp_push_pending_frames(struct sock *sk,
+ struct tcp_opt *tp)
+{
+#if 0
+ __tcp_push_pending_frames(sk, tp, tcp_current_mss(sk), tp->nonagle);
+#endif
+}
+
+static __inline__ int tcp_may_send_now(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+ struct sk_buff *skb = tp->send_head;
+
+ return (skb &&
+ tcp_snd_test(tp, skb, tcp_current_mss(sk),
+ tcp_skb_is_last(sk, skb) ? 1 : tp->nonagle));
+#else
+ return 0;
+#endif
+}
+
+static __inline__ void tcp_init_wl(struct tcp_opt *tp, u32 ack, u32 seq)
+{
+#if 0
+ tp->snd_wl1 = seq;
+#endif
+}
+
+static __inline__ void tcp_update_wl(struct tcp_opt *tp, u32 ack, u32 seq)
+{
+#if 0
+ tp->snd_wl1 = seq;
+#endif
+}
+
+extern void tcp_destroy_sock(struct sock *sk);
+
+
+/*
+ * Calculate(/check) TCP checksum
+ */
+static __inline__ u16 tcp_v4_check(struct tcphdr *th, int len,
+ unsigned long saddr, unsigned long daddr,
+ unsigned long base)
+{
+#if 0
+ return csum_tcpudp_magic(saddr,daddr,len,IPPROTO_TCP,base);
+#else
+ return 0;
+#endif
+}
+
+static __inline__ int __tcp_checksum_complete(struct sk_buff *skb)
+{
+#if 0
+ return (unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum));
+#else
+ return 0;
+#endif
+}
+
+static __inline__ int tcp_checksum_complete(struct sk_buff *skb)
+{
+#if 0
+ return skb->ip_summed != CHECKSUM_UNNECESSARY &&
+ __tcp_checksum_complete(skb);
+#else
+ return 0;
+#endif
+}
+
+/* Prequeue for VJ style copy to user, combined with checksumming. */
+
+static __inline__ void tcp_prequeue_init(struct tcp_opt *tp)
+{
+#if 0
+ tp->ucopy.task = NULL;
+ tp->ucopy.len = 0;
+ tp->ucopy.memory = 0;
+ skb_queue_head_init(&tp->ucopy.prequeue);
+#endif
+}
+
+/* Packet is added to VJ-style prequeue for processing in process
+ * context, if a reader task is waiting. Apparently, this exciting
+ * idea (VJ's mail "Re: query about TCP header on tcp-ip" of 07 Sep 93)
+ * failed somewhere. Latency? Burstiness? Well, at least now we will
+ * see, why it failed. 8)8) --ANK
+ *
+ * NOTE: is this not too big to inline?
+ */
+static __inline__ int tcp_prequeue(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ if (tp->ucopy.task) {
+ __skb_queue_tail(&tp->ucopy.prequeue, skb);
+ tp->ucopy.memory += skb->truesize;
+ if (tp->ucopy.memory > sk->rcvbuf) {
+ struct sk_buff *skb1;
+
+ if (sk->lock.users)
+ out_of_line_bug();
+
+ while ((skb1 = __skb_dequeue(&tp->ucopy.prequeue)) != NULL) {
+ sk->backlog_rcv(sk, skb1);
+ NET_INC_STATS_BH(TCPPrequeueDropped);
+ }
+
+ tp->ucopy.memory = 0;
+ } else if (skb_queue_len(&tp->ucopy.prequeue) == 1) {
+ wake_up_interruptible(sk->sleep);
+ if (!tcp_ack_scheduled(tp))
+ tcp_reset_xmit_timer(sk, TCP_TIME_DACK, (3*TCP_RTO_MIN)/4);
+ }
+ return 1;
+ }
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+
+#undef STATE_TRACE
+
+#ifdef STATE_TRACE
+static char *statename[]={
+ "Unused","Established","Syn Sent","Syn Recv",
+ "Fin Wait 1","Fin Wait 2","Time Wait", "Close",
+ "Close Wait","Last ACK","Listen","Closing"
+};
+#endif
+
+static __inline__ void tcp_set_state(struct sock *sk, int state)
+{
+#if 0
+ int oldstate = sk->state;
+
+ switch (state) {
+ case TCP_ESTABLISHED:
+ if (oldstate != TCP_ESTABLISHED)
+ TCP_INC_STATS(TcpCurrEstab);
+ break;
+
+ case TCP_CLOSE:
+ sk->prot->unhash(sk);
+ if (sk->prev && !(sk->userlocks&SOCK_BINDPORT_LOCK))
+ tcp_put_port(sk);
+ /* fall through */
+ default:
+ if (oldstate==TCP_ESTABLISHED)
+ tcp_statistics[smp_processor_id()*2+!in_softirq()].TcpCurrEstab--;
+ }
+
+ /* Change state AFTER socket is unhashed to avoid closed
+ * socket sitting in hash tables.
+ */
+ sk->state = state;
+
+#ifdef STATE_TRACE
+ SOCK_DEBUG(sk, "TCP sk=%p, State %s -> %s\n",sk, statename[oldstate],statename[state]);
+#endif
+#endif
+}
+
+static __inline__ void tcp_done(struct sock *sk)
+{
+#if 0
+ tcp_set_state(sk, TCP_CLOSE);
+ tcp_clear_xmit_timers(sk);
+
+ sk->shutdown = SHUTDOWN_MASK;
+
+ if (!sk->dead)
+ sk->state_change(sk);
+ else
+ tcp_destroy_sock(sk);
+#endif
+}
+
+static __inline__ void tcp_sack_reset(struct tcp_opt *tp)
+{
+#if 0
+ tp->dsack = 0;
+ tp->eff_sacks = 0;
+ tp->num_sacks = 0;
+#endif
+}
+
+static __inline__ void tcp_build_and_update_options(__u32 *ptr, struct tcp_opt *tp, __u32 tstamp)
+{
+#if 0
+ if (tp->tstamp_ok) {
+ *ptr++ = __constant_htonl((TCPOPT_NOP << 24) |
+ (TCPOPT_NOP << 16) |
+ (TCPOPT_TIMESTAMP << 8) |
+ TCPOLEN_TIMESTAMP);
+ *ptr++ = htonl(tstamp);
+ *ptr++ = htonl(tp->ts_recent);
+ }
+ if (tp->eff_sacks) {
+ struct tcp_sack_block *sp = tp->dsack ? tp->duplicate_sack : tp->selective_acks;
+ int this_sack;
+
+ *ptr++ = __constant_htonl((TCPOPT_NOP << 24) |
+ (TCPOPT_NOP << 16) |
+ (TCPOPT_SACK << 8) |
+ (TCPOLEN_SACK_BASE +
+ (tp->eff_sacks * TCPOLEN_SACK_PERBLOCK)));
+ for(this_sack = 0; this_sack < tp->eff_sacks; this_sack++) {
+ *ptr++ = htonl(sp[this_sack].start_seq);
+ *ptr++ = htonl(sp[this_sack].end_seq);
+ }
+ if (tp->dsack) {
+ tp->dsack = 0;
+ tp->eff_sacks--;
+ }
+ }
+#endif
+}
+
+/* Construct a tcp options header for a SYN or SYN_ACK packet.
+ * If this is every changed make sure to change the definition of
+ * MAX_SYN_SIZE to match the new maximum number of options that you
+ * can generate.
+ */
+static inline void tcp_syn_build_options(__u32 *ptr, int mss, int ts, int sack,
+ int offer_wscale, int wscale, __u32 tstamp, __u32 ts_recent)
+{
+#if 0
+ /* We always get an MSS option.
+ * The option bytes which will be seen in normal data
+ * packets should timestamps be used, must be in the MSS
+ * advertised. But we subtract them from tp->mss_cache so
+ * that calculations in tcp_sendmsg are simpler etc.
+ * So account for this fact here if necessary. If we
+ * don't do this correctly, as a receiver we won't
+ * recognize data packets as being full sized when we
+ * should, and thus we won't abide by the delayed ACK
+ * rules correctly.
+ * SACKs don't matter, we never delay an ACK when we
+ * have any of those going out.
+ */
+ *ptr++ = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | mss);
+ if (ts) {
+ if(sack)
+ *ptr++ = __constant_htonl((TCPOPT_SACK_PERM << 24) | (TCPOLEN_SACK_PERM << 16) |
+ (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+ else
+ *ptr++ = __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
+ (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+ *ptr++ = htonl(tstamp); /* TSVAL */
+ *ptr++ = htonl(ts_recent); /* TSECR */
+ } else if(sack)
+ *ptr++ = __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
+ (TCPOPT_SACK_PERM << 8) | TCPOLEN_SACK_PERM);
+ if (offer_wscale)
+ *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_WINDOW << 16) | (TCPOLEN_WINDOW << 8) | (wscale));
+#endif
+}
+
+/* Determine a window scaling and initial window to offer.
+ * Based on the assumption that the given amount of space
+ * will be offered. Store the results in the tp structure.
+ * NOTE: for smooth operation initial space offering should
+ * be a multiple of mss if possible. We assume here that mss >= 1.
+ * This MUST be enforced by all callers.
+ */
+static inline void tcp_select_initial_window(int __space, __u32 mss,
+ __u32 *rcv_wnd,
+ __u32 *window_clamp,
+ int wscale_ok,
+ __u8 *rcv_wscale)
+{
+#if 0
+ unsigned int space = (__space < 0 ? 0 : __space);
+
+ /* If no clamp set the clamp to the max possible scaled window */
+ if (*window_clamp == 0)
+ (*window_clamp) = (65535 << 14);
+ space = min(*window_clamp, space);
+
+ /* Quantize space offering to a multiple of mss if possible. */
+ if (space > mss)
+ space = (space / mss) * mss;
+
+ /* NOTE: offering an initial window larger than 32767
+ * will break some buggy TCP stacks. We try to be nice.
+ * If we are not window scaling, then this truncates
+ * our initial window offering to 32k. There should also
+ * be a sysctl option to stop being nice.
+ */
+ (*rcv_wnd) = min(space, MAX_TCP_WINDOW);
+ (*rcv_wscale) = 0;
+ if (wscale_ok) {
+ /* See RFC1323 for an explanation of the limit to 14 */
+ while (space > 65535 && (*rcv_wscale) < 14) {
+ space >>= 1;
+ (*rcv_wscale)++;
+ }
+ if (*rcv_wscale && sysctl_tcp_app_win && space>=mss &&
+ space - max((space>>sysctl_tcp_app_win), mss>>*rcv_wscale) < 65536/2)
+ (*rcv_wscale)--;
+ }
+
+ /* Set initial window to value enough for senders,
+ * following RFC1414. Senders, not following this RFC,
+ * will be satisfied with 2.
+ */
+ if (mss > (1<<*rcv_wscale)) {
+ int init_cwnd = 4;
+ if (mss > 1460*3)
+ init_cwnd = 2;
+ else if (mss > 1460)
+ init_cwnd = 3;
+ if (*rcv_wnd > init_cwnd*mss)
+ *rcv_wnd = init_cwnd*mss;
+ }
+ /* Set the clamp no higher than max representable value */
+ (*window_clamp) = min(65535U << (*rcv_wscale), *window_clamp);
+#endif
+}
+
+static inline int tcp_win_from_space(int space)
+{
+#if 0
+ return sysctl_tcp_adv_win_scale<=0 ?
+ (space>>(-sysctl_tcp_adv_win_scale)) :
+ space - (space>>sysctl_tcp_adv_win_scale);
+#else
+ return 0;
+#endif
+}
+
+/* Note: caller must be prepared to deal with negative returns */
+static inline int tcp_space(struct sock *sk)
+{
+#if 0
+ return tcp_win_from_space(sk->rcvbuf - atomic_read(&sk->rmem_alloc));
+#else
+ return 0;
+#endif
+}
+
+static inline int tcp_full_space( struct sock *sk)
+{
+#if 0
+ return tcp_win_from_space(sk->rcvbuf);
+#else
+ return 0;
+#endif
+}
+
+static inline void tcp_acceptq_removed(struct sock *sk)
+{
+#if 0
+ sk->ack_backlog--;
+#endif
+}
+
+static inline void tcp_acceptq_added(struct sock *sk)
+{
+#if 0
+ sk->ack_backlog++;
+#endif
+}
+
+static inline int tcp_acceptq_is_full(struct sock *sk)
+{
+#if 0
+ return sk->ack_backlog > sk->max_ack_backlog;
+#else
+ return 0;
+#endif
+}
+
+static inline void tcp_acceptq_queue(struct sock *sk, struct open_request *req,
+ struct sock *child)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ req->sk = child;
+ tcp_acceptq_added(sk);
+
+ if (!tp->accept_queue_tail) {
+ tp->accept_queue = req;
+ } else {
+ tp->accept_queue_tail->dl_next = req;
+ }
+ tp->accept_queue_tail = req;
+ req->dl_next = NULL;
+#endif
+}
+
+struct tcp_listen_opt
+{
+ u8 max_qlen_log; /* log_2 of maximal queued SYNs */
+ int qlen;
+ int qlen_young;
+ int clock_hand;
+ struct open_request *syn_table[TCP_SYNQ_HSIZE];
+};
+
+static inline void
+tcp_synq_removed(struct sock *sk, struct open_request *req)
+{
+#if 0
+ struct tcp_listen_opt *lopt = sk->tp_pinfo.af_tcp.listen_opt;
+
+ if (--lopt->qlen == 0)
+ tcp_delete_keepalive_timer(sk);
+ if (req->retrans == 0)
+ lopt->qlen_young--;
+#endif
+}
+
+static inline void tcp_synq_added(struct sock *sk)
+{
+#if 0
+ struct tcp_listen_opt *lopt = sk->tp_pinfo.af_tcp.listen_opt;
+
+ if (lopt->qlen++ == 0)
+ tcp_reset_keepalive_timer(sk, TCP_TIMEOUT_INIT);
+ lopt->qlen_young++;
+#endif
+}
+
+static inline int tcp_synq_len(struct sock *sk)
+{
+#if 0
+ return sk->tp_pinfo.af_tcp.listen_opt->qlen;
+#else
+ return 0;
+#endif
+}
+
+static inline int tcp_synq_young(struct sock *sk)
+{
+#if 0
+ return sk->tp_pinfo.af_tcp.listen_opt->qlen_young;
+#else
+ return 0;
+#endif
+}
+
+static inline int tcp_synq_is_full(struct sock *sk)
+{
+#if 0
+ return tcp_synq_len(sk)>>sk->tp_pinfo.af_tcp.listen_opt->max_qlen_log;
+#else
+ return 0;
+#endif
+}
+
+static inline void tcp_synq_unlink(struct tcp_opt *tp, struct open_request *req,
+ struct open_request **prev)
+{
+#if 0
+ write_lock(&tp->syn_wait_lock);
+ *prev = req->dl_next;
+ write_unlock(&tp->syn_wait_lock);
+#endif
+}
+
+static inline void tcp_synq_drop(struct sock *sk, struct open_request *req,
+ struct open_request **prev)
+{
+#if 0
+ tcp_synq_unlink(&sk->tp_pinfo.af_tcp, req, prev);
+ tcp_synq_removed(sk, req);
+ tcp_openreq_free(req);
+#endif
+}
+
+static __inline__ void tcp_openreq_init(struct open_request *req,
+ struct tcp_opt *tp,
+ struct sk_buff *skb)
+{
+#if 0
+ req->rcv_wnd = 0; /* So that tcp_send_synack() knows! */
+ req->rcv_isn = TCP_SKB_CB(skb)->seq;
+ req->mss = tp->mss_clamp;
+ req->ts_recent = tp->saw_tstamp ? tp->rcv_tsval : 0;
+ req->tstamp_ok = tp->tstamp_ok;
+ req->sack_ok = tp->sack_ok;
+ req->snd_wscale = tp->snd_wscale;
+ req->wscale_ok = tp->wscale_ok;
+ req->acked = 0;
+ req->ecn_ok = 0;
+ req->rmt_port = skb->h.th->source;
+#endif
+}
+
+#define TCP_MEM_QUANTUM ((int)PAGE_SIZE)
+
+static inline void tcp_free_skb(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+ sk->tp_pinfo.af_tcp.queue_shrunk = 1;
+ sk->wmem_queued -= skb->truesize;
+ sk->forward_alloc += skb->truesize;
+ __kfree_skb(skb);
+#endif
+}
+
+static inline void tcp_charge_skb(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+ sk->wmem_queued += skb->truesize;
+ sk->forward_alloc -= skb->truesize;
+#endif
+}
+
+extern void __tcp_mem_reclaim(struct sock *sk);
+extern int tcp_mem_schedule(struct sock *sk, int size, int kind);
+
+static inline void tcp_mem_reclaim(struct sock *sk)
+{
+#if 0
+ if (sk->forward_alloc >= TCP_MEM_QUANTUM)
+ __tcp_mem_reclaim(sk);
+#endif
+}
+
+static inline void tcp_enter_memory_pressure(void)
+{
+#if 0
+ if (!tcp_memory_pressure) {
+ NET_INC_STATS(TCPMemoryPressures);
+ tcp_memory_pressure = 1;
+ }
+#endif
+}
+
+static inline void tcp_moderate_sndbuf(struct sock *sk)
+{
+#if 0
+ if (!(sk->userlocks&SOCK_SNDBUF_LOCK)) {
+ sk->sndbuf = min(sk->sndbuf, sk->wmem_queued/2);
+ sk->sndbuf = max(sk->sndbuf, SOCK_MIN_SNDBUF);
+ }
+#endif
+}
+
+static inline struct sk_buff *tcp_alloc_pskb(struct sock *sk, int size, int mem, int gfp)
+{
+#if 0
+ struct sk_buff *skb = alloc_skb(size+MAX_TCP_HEADER, gfp);
+
+ if (skb) {
+ skb->truesize += mem;
+ if (sk->forward_alloc >= (int)skb->truesize ||
+ tcp_mem_schedule(sk, skb->truesize, 0)) {
+ skb_reserve(skb, MAX_TCP_HEADER);
+ return skb;
+ }
+ __kfree_skb(skb);
+ } else {
+ tcp_enter_memory_pressure();
+ tcp_moderate_sndbuf(sk);
+ }
+ return NULL;
+#else
+ return NULL;
+#endif
+}
+
+static inline struct sk_buff *tcp_alloc_skb(struct sock *sk, int size, int gfp)
+{
+#if 0
+ return tcp_alloc_pskb(sk, size, 0, gfp);
+#else
+ return NULL;
+#endif
+}
+
+static inline struct page * tcp_alloc_page(struct sock *sk)
+{
+#if 0
+ if (sk->forward_alloc >= (int)PAGE_SIZE ||
+ tcp_mem_schedule(sk, PAGE_SIZE, 0)) {
+ struct page *page = alloc_pages(sk->allocation, 0);
+ if (page)
+ return page;
+ }
+ tcp_enter_memory_pressure();
+ tcp_moderate_sndbuf(sk);
+ return NULL;
+#else
+ return NULL;
+#endif
+}
+
+static inline void tcp_writequeue_purge(struct sock *sk)
+{
+#if 0
+ struct sk_buff *skb;
+
+ while ((skb = __skb_dequeue(&sk->write_queue)) != NULL)
+ tcp_free_skb(sk, skb);
+ tcp_mem_reclaim(sk);
+#endif
+}
+
+extern void tcp_rfree(struct sk_buff *skb);
+
+static inline void tcp_set_owner_r(struct sk_buff *skb, struct sock *sk)
+{
+#if 0
+ skb->sk = sk;
+ skb->destructor = tcp_rfree;
+ atomic_add(skb->truesize, &sk->rmem_alloc);
+ sk->forward_alloc -= skb->truesize;
+#endif
+}
+
+extern void tcp_listen_wlock(void);
+
+/* - We may sleep inside this lock.
+ * - If sleeping is not required (or called from BH),
+ * use plain read_(un)lock(&tcp_lhash_lock).
+ */
+
+static inline void tcp_listen_lock(void)
+{
+#if 0
+ /* read_lock synchronizes to candidates to writers */
+ read_lock(&tcp_lhash_lock);
+ atomic_inc(&tcp_lhash_users);
+ read_unlock(&tcp_lhash_lock);
+#endif
+}
+
+static inline void tcp_listen_unlock(void)
+{
+#if 0
+ if (atomic_dec_and_test(&tcp_lhash_users))
+ wake_up(&tcp_lhash_wait);
+#endif
+}
+
+static inline int keepalive_intvl_when(struct tcp_opt *tp)
+{
+#if 0
+ return tp->keepalive_intvl ? : sysctl_tcp_keepalive_intvl;
+#else
+ return 0;
+#endif
+}
+
+static inline int keepalive_time_when(struct tcp_opt *tp)
+{
+#if 0
+ return tp->keepalive_time ? : sysctl_tcp_keepalive_time;
+#else
+ return 0;
+#endif
+}
+
+static inline int tcp_fin_time(struct tcp_opt *tp)
+{
+#if 0
+ int fin_timeout = tp->linger2 ? : sysctl_tcp_fin_timeout;
+
+ if (fin_timeout < (tp->rto<<2) - (tp->rto>>1))
+ fin_timeout = (tp->rto<<2) - (tp->rto>>1);
+
+ return fin_timeout;
+#else
+ return 0;
+#endif
+}
+
+static inline int tcp_paws_check(struct tcp_opt *tp, int rst)
+{
+#if 0
+ if ((s32)(tp->rcv_tsval - tp->ts_recent) >= 0)
+ return 0;
+ if (xtime.tv_sec >= tp->ts_recent_stamp + TCP_PAWS_24DAYS)
+ return 0;
+
+ /* RST segments are not recommended to carry timestamp,
+ and, if they do, it is recommended to ignore PAWS because
+ "their cleanup function should take precedence over timestamps."
+ Certainly, it is mistake. It is necessary to understand the reasons
+ of this constraint to relax it: if peer reboots, clock may go
+ out-of-sync and half-open connections will not be reset.
+ Actually, the problem would be not existing if all
+ the implementations followed draft about maintaining clock
+ via reboots. Linux-2.2 DOES NOT!
+
+ However, we can relax time bounds for RST segments to MSL.
+ */
+ if (rst && xtime.tv_sec >= tp->ts_recent_stamp + TCP_PAWS_MSL)
+ return 0;
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+#define TCP_CHECK_TIMER(sk) do { } while (0)
+
+#endif /* __TCPCORE_H */
+
+
+//
+#endif
+#endif
--- /dev/null
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Definitions for the TCP protocol.
+ *
+ * Version: @(#)tcp.h 1.0.2 04/28/93
+ *
+ * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_TCP_H
+#define _LINUX_TCP_H
+
+#include "linux.h"
+
+struct tcphdr {
+ __u16 source;
+ __u16 dest;
+ __u32 seq;
+ __u32 ack_seq;
+//#if defined(__LITTLE_ENDIAN_BITFIELD)
+ __u16 res1:4,
+ doff:4,
+ fin:1,
+ syn:1,
+ rst:1,
+ psh:1,
+ ack:1,
+ urg:1,
+ ece:1,
+ cwr:1;
+/*#elif defined(__BIG_ENDIAN_BITFIELD)
+ __u16 doff:4,
+ res1:4,
+ cwr:1,
+ ece:1,
+ urg:1,
+ ack:1,
+ psh:1,
+ rst:1,
+ syn:1,
+ fin:1;
+#else
+#error "Adjust your <asm/byteorder.h> defines"
+#endif */
+ __u16 window;
+ __u16 check;
+ __u16 urg_ptr;
+};
+
+
+enum {
+ TCP_ESTABLISHED = 1,
+ TCP_SYN_SENT,
+ TCP_SYN_RECV,
+ TCP_FIN_WAIT1,
+ TCP_FIN_WAIT2,
+ TCP_TIME_WAIT,
+ TCP_CLOSE,
+ TCP_CLOSE_WAIT,
+ TCP_LAST_ACK,
+ TCP_LISTEN,
+ TCP_CLOSING, /* now a valid state */
+
+ TCP_MAX_STATES /* Leave at the end! */
+};
+
+#define TCP_STATE_MASK 0xF
+#define TCP_ACTION_FIN (1 << 7)
+
+enum {
+ TCPF_ESTABLISHED = (1 << 1),
+ TCPF_SYN_SENT = (1 << 2),
+ TCPF_SYN_RECV = (1 << 3),
+ TCPF_FIN_WAIT1 = (1 << 4),
+ TCPF_FIN_WAIT2 = (1 << 5),
+ TCPF_TIME_WAIT = (1 << 6),
+ TCPF_CLOSE = (1 << 7),
+ TCPF_CLOSE_WAIT = (1 << 8),
+ TCPF_LAST_ACK = (1 << 9),
+ TCPF_LISTEN = (1 << 10),
+ TCPF_CLOSING = (1 << 11)
+};
+
+/*
+ * The union cast uses a gcc extension to avoid aliasing problems
+ * (union is compatible to any of its members)
+ * This means this part of the code is -fstrict-aliasing safe now.
+ */
+union tcp_word_hdr {
+ struct tcphdr hdr;
+ __u32 words[5];
+};
+
+#define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words [3])
+
+enum {
+ TCP_FLAG_CWR = 0x00800000, // __constant_htonl(0x00800000),
+ TCP_FLAG_ECE = 0x00400000, //__constant_htonl(0x00400000),
+ TCP_FLAG_URG = 0x00200000, //__constant_htonl(0x00200000),
+ TCP_FLAG_ACK = 0x00100000, //__constant_htonl(0x00100000),
+ TCP_FLAG_PSH = 0x00080000, //__constant_htonl(0x00080000),
+ TCP_FLAG_RST = 0x00040000, //__constant_htonl(0x00040000),
+ TCP_FLAG_SYN = 0x00020000, //__constant_htonl(0x00020000),
+ TCP_FLAG_FIN = 0x00010000, //__constant_htonl(0x00010000),
+ TCP_RESERVED_BITS = 0x0F000000, //__constant_htonl(0x0F000000),
+ TCP_DATA_OFFSET = 0xF0000000, //__constant_htonl(0xF0000000)
+};
+
+/* TCP socket options */
+#define TCP_NODELAY 1 /* Turn off Nagle's algorithm. */
+#define TCP_MAXSEG 2 /* Limit MSS */
+#define TCP_CORK 3 /* Never send partially complete segments */
+#define TCP_KEEPIDLE 4 /* Start keeplives after this period */
+#define TCP_KEEPINTVL 5 /* Interval between keepalives */
+#define TCP_KEEPCNT 6 /* Number of keepalives before death */
+#define TCP_SYNCNT 7 /* Number of SYN retransmits */
+#define TCP_LINGER2 8 /* Life time of orphaned FIN-WAIT-2 state */
+#define TCP_DEFER_ACCEPT 9 /* Wake up listener only when data arrive */
+#define TCP_WINDOW_CLAMP 10 /* Bound advertised window */
+#define TCP_INFO 11 /* Information about this connection. */
+#define TCP_QUICKACK 12 /* Block/reenable quick acks */
+
+#define TCPI_OPT_TIMESTAMPS 1
+#define TCPI_OPT_SACK 2
+#define TCPI_OPT_WSCALE 4
+#define TCPI_OPT_ECN 8
+
+enum tcp_ca_state
+{
+ TCP_CA_Open = 0,
+#define TCPF_CA_Open (1<<TCP_CA_Open)
+ TCP_CA_Disorder = 1,
+#define TCPF_CA_Disorder (1<<TCP_CA_Disorder)
+ TCP_CA_CWR = 2,
+#define TCPF_CA_CWR (1<<TCP_CA_CWR)
+ TCP_CA_Recovery = 3,
+#define TCPF_CA_Recovery (1<<TCP_CA_Recovery)
+ TCP_CA_Loss = 4
+#define TCPF_CA_Loss (1<<TCP_CA_Loss)
+};
+
+struct tcp_info
+{
+ __u8 tcpi_state;
+ __u8 tcpi_ca_state;
+ __u8 tcpi_retransmits;
+ __u8 tcpi_probes;
+ __u8 tcpi_backoff;
+ __u8 tcpi_options;
+ __u8 tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4;
+
+ __u32 tcpi_rto;
+ __u32 tcpi_ato;
+ __u32 tcpi_snd_mss;
+ __u32 tcpi_rcv_mss;
+
+ __u32 tcpi_unacked;
+ __u32 tcpi_sacked;
+ __u32 tcpi_lost;
+ __u32 tcpi_retrans;
+ __u32 tcpi_fackets;
+
+ /* Times. */
+ __u32 tcpi_last_data_sent;
+ __u32 tcpi_last_ack_sent; /* Not remembered, sorry. */
+ __u32 tcpi_last_data_recv;
+ __u32 tcpi_last_ack_recv;
+
+ /* Metrics. */
+ __u32 tcpi_pmtu;
+ __u32 tcpi_rcv_ssthresh;
+ __u32 tcpi_rtt;
+ __u32 tcpi_rttvar;
+ __u32 tcpi_snd_ssthresh;
+ __u32 tcpi_snd_cwnd;
+ __u32 tcpi_advmss;
+ __u32 tcpi_reordering;
+};
+
+#endif /* _LINUX_TCP_H */
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS TCP/IP protocol driver
+ * FILE: transport/tcp/tcp_input.c
+ * PURPOSE: Transmission Control Protocol
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISIONS:
+ * CSH 15-01-2003 Imported from linux kernel 2.4.20
+ */
+
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Implementation of the Transmission Control Protocol(TCP).
+ *
+ * Version: $Id$
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Mark Evans, <evansmp@uhura.aston.ac.uk>
+ * Corey Minyard <wf-rch!minyard@relay.EU.net>
+ * Florian La Roche, <flla@stud.uni-sb.de>
+ * Charles Hedrick, <hedrick@klinzhai.rutgers.edu>
+ * Linus Torvalds, <torvalds@cs.helsinki.fi>
+ * Alan Cox, <gw4pts@gw4pts.ampr.org>
+ * Matthew Dillon, <dillon@apollo.west.oic.com>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Jorge Cwik, <jorge@laser.satlink.net>
+ */
+
+/*
+ * Changes:
+ * Pedro Roque : Fast Retransmit/Recovery.
+ * Two receive queues.
+ * Retransmit queue handled by TCP.
+ * Better retransmit timer handling.
+ * New congestion avoidance.
+ * Header prediction.
+ * Variable renaming.
+ *
+ * Eric : Fast Retransmit.
+ * Randy Scott : MSS option defines.
+ * Eric Schenk : Fixes to slow start algorithm.
+ * Eric Schenk : Yet another double ACK bug.
+ * Eric Schenk : Delayed ACK bug fixes.
+ * Eric Schenk : Floyd style fast retrans war avoidance.
+ * David S. Miller : Don't allow zero congestion window.
+ * Eric Schenk : Fix retransmitter so that it sends
+ * next packet on ack of previous packet.
+ * Andi Kleen : Moved open_request checking here
+ * and process RSTs for open_requests.
+ * Andi Kleen : Better prune_queue, and other fixes.
+ * Andrey Savochkin: Fix RTT measurements in the presnce of
+ * timestamps.
+ * Andrey Savochkin: Check sequence numbers correctly when
+ * removing SACKs due to in sequence incoming
+ * data segments.
+ * Andi Kleen: Make sure we never ack data there is not
+ * enough room for. Also make this condition
+ * a fatal error if it might still happen.
+ * Andi Kleen: Add tcp_measure_rcv_mss to make
+ * connections with MSS<min(MTU,ann. MSS)
+ * work without delayed acks.
+ * Andi Kleen: Process packets with PSH set in the
+ * fast path.
+ * J Hadi Salim: ECN support
+ * Andrei Gurtov,
+ * Pasi Sarolahti,
+ * Panu Kuhlberg: Experimental audit of TCP (re)transmission
+ * engine. Lots of bugs are found.
+ */
+
+#if 0
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/sysctl.h>
+#include <net/tcp.h>
+#include <net/inet_common.h>
+#include <linux/ipsec.h>
+#else
+#include "linux.h"
+#include "tcpcore.h"
+#endif
+
+int sysctl_tcp_timestamps = 1;
+int sysctl_tcp_window_scaling = 1;
+int sysctl_tcp_sack = 1;
+int sysctl_tcp_fack = 1;
+int sysctl_tcp_reordering = TCP_FASTRETRANS_THRESH;
+#ifdef CONFIG_INET_ECN
+int sysctl_tcp_ecn = 1;
+#else
+int sysctl_tcp_ecn = 0;
+#endif
+int sysctl_tcp_dsack = 1;
+int sysctl_tcp_app_win = 31;
+int sysctl_tcp_adv_win_scale = 2;
+
+int sysctl_tcp_stdurg = 0;
+int sysctl_tcp_rfc1337 = 0;
+//int sysctl_tcp_max_orphans = NR_FILE;
+
+#define FLAG_DATA 0x01 /* Incoming frame contained data. */
+#define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */
+#define FLAG_DATA_ACKED 0x04 /* This ACK acknowledged new data. */
+#define FLAG_RETRANS_DATA_ACKED 0x08 /* "" "" some of which was retransmitted. */
+#define FLAG_SYN_ACKED 0x10 /* This ACK acknowledged SYN. */
+#define FLAG_DATA_SACKED 0x20 /* New SACK. */
+#define FLAG_ECE 0x40 /* ECE in this ACK */
+#define FLAG_DATA_LOST 0x80 /* SACK detected data lossage. */
+#define FLAG_SLOWPATH 0x100 /* Do not skip RFC checks for window update.*/
+
+#define FLAG_ACKED (FLAG_DATA_ACKED|FLAG_SYN_ACKED)
+#define FLAG_NOT_DUP (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED)
+#define FLAG_CA_ALERT (FLAG_DATA_SACKED|FLAG_ECE)
+#define FLAG_FORWARD_PROGRESS (FLAG_ACKED|FLAG_DATA_SACKED)
+
+#define IsReno(tp) ((tp)->sack_ok == 0)
+#define IsFack(tp) ((tp)->sack_ok & 2)
+#define IsDSack(tp) ((tp)->sack_ok & 4)
+
+#define TCP_REMNANT (TCP_FLAG_FIN|TCP_FLAG_URG|TCP_FLAG_SYN|TCP_FLAG_PSH)
+
+/* Adapt the MSS value used to make delayed ack decision to the
+ * real world.
+ */
+static __inline__ void tcp_measure_rcv_mss(struct tcp_opt *tp, struct sk_buff *skb)
+{
+#if 0
+ unsigned int len, lss;
+
+ lss = tp->ack.last_seg_size;
+ tp->ack.last_seg_size = 0;
+
+ /* skb->len may jitter because of SACKs, even if peer
+ * sends good full-sized frames.
+ */
+ len = skb->len;
+ if (len >= tp->ack.rcv_mss) {
+ tp->ack.rcv_mss = len;
+ } else {
+ /* Otherwise, we make more careful check taking into account,
+ * that SACKs block is variable.
+ *
+ * "len" is invariant segment length, including TCP header.
+ */
+ len += skb->data - skb->h.raw;
+ if (len >= TCP_MIN_RCVMSS + sizeof(struct tcphdr) ||
+ /* If PSH is not set, packet should be
+ * full sized, provided peer TCP is not badly broken.
+ * This observation (if it is correct 8)) allows
+ * to handle super-low mtu links fairly.
+ */
+ (len >= TCP_MIN_MSS + sizeof(struct tcphdr) &&
+ !(tcp_flag_word(skb->h.th)&TCP_REMNANT))) {
+ /* Subtract also invariant (if peer is RFC compliant),
+ * tcp header plus fixed timestamp option length.
+ * Resulting "len" is MSS free of SACK jitter.
+ */
+ len -= tp->tcp_header_len;
+ tp->ack.last_seg_size = len;
+ if (len == lss) {
+ tp->ack.rcv_mss = len;
+ return;
+ }
+ }
+ tp->ack.pending |= TCP_ACK_PUSHED;
+ }
+#endif
+}
+
+static void tcp_incr_quickack(struct tcp_opt *tp)
+{
+#if 0
+ unsigned quickacks = tp->rcv_wnd/(2*tp->ack.rcv_mss);
+
+ if (quickacks==0)
+ quickacks=2;
+ if (quickacks > tp->ack.quick)
+ tp->ack.quick = min(quickacks, TCP_MAX_QUICKACKS);
+#endif
+}
+
+void tcp_enter_quickack_mode(struct tcp_opt *tp)
+{
+#if 0
+ tcp_incr_quickack(tp);
+ tp->ack.pingpong = 0;
+ tp->ack.ato = TCP_ATO_MIN;
+#endif
+}
+
+/* Send ACKs quickly, if "quick" count is not exhausted
+ * and the session is not interactive.
+ */
+
+static __inline__ int tcp_in_quickack_mode(struct tcp_opt *tp)
+{
+#if 0
+ return (tp->ack.quick && !tp->ack.pingpong);
+#else
+ return 0;
+#endif
+}
+
+/* Buffer size and advertised window tuning.
+ *
+ * 1. Tuning sk->sndbuf, when connection enters established state.
+ */
+
+static void tcp_fixup_sndbuf(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int sndmem = tp->mss_clamp+MAX_TCP_HEADER+16+sizeof(struct sk_buff);
+
+ if (sk->sndbuf < 3*sndmem)
+ sk->sndbuf = min(3*sndmem, sysctl_tcp_wmem[2]);
+#endif
+}
+
+/* 2. Tuning advertised window (window_clamp, rcv_ssthresh)
+ *
+ * All tcp_full_space() is split to two parts: "network" buffer, allocated
+ * forward and advertised in receiver window (tp->rcv_wnd) and
+ * "application buffer", required to isolate scheduling/application
+ * latencies from network.
+ * window_clamp is maximal advertised window. It can be less than
+ * tcp_full_space(), in this case tcp_full_space() - window_clamp
+ * is reserved for "application" buffer. The less window_clamp is
+ * the smoother our behaviour from viewpoint of network, but the lower
+ * throughput and the higher sensitivity of the connection to losses. 8)
+ *
+ * rcv_ssthresh is more strict window_clamp used at "slow start"
+ * phase to predict further behaviour of this connection.
+ * It is used for two goals:
+ * - to enforce header prediction at sender, even when application
+ * requires some significant "application buffer". It is check #1.
+ * - to prevent pruning of receive queue because of misprediction
+ * of receiver window. Check #2.
+ *
+ * The scheme does not work when sender sends good segments opening
+ * window and then starts to feed us spagetti. But it should work
+ * in common situations. Otherwise, we have to rely on queue collapsing.
+ */
+
+/* Slow part of check#2. */
+static int
+__tcp_grow_window(struct sock *sk, struct tcp_opt *tp, struct sk_buff *skb)
+{
+#if 0
+ /* Optimize this! */
+ int truesize = tcp_win_from_space(skb->truesize)/2;
+ int window = tcp_full_space(sk)/2;
+
+ while (tp->rcv_ssthresh <= window) {
+ if (truesize <= skb->len)
+ return 2*tp->ack.rcv_mss;
+
+ truesize >>= 1;
+ window >>= 1;
+ }
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+static __inline__ void
+tcp_grow_window(struct sock *sk, struct tcp_opt *tp, struct sk_buff *skb)
+{
+#if 0
+ /* Check #1 */
+ if (tp->rcv_ssthresh < tp->window_clamp &&
+ (int)tp->rcv_ssthresh < tcp_space(sk) &&
+ !tcp_memory_pressure) {
+ int incr;
+
+ /* Check #2. Increase window, if skb with such overhead
+ * will fit to rcvbuf in future.
+ */
+ if (tcp_win_from_space(skb->truesize) <= skb->len)
+ incr = 2*tp->advmss;
+ else
+ incr = __tcp_grow_window(sk, tp, skb);
+
+ if (incr) {
+ tp->rcv_ssthresh = min(tp->rcv_ssthresh + incr, tp->window_clamp);
+ tp->ack.quick |= 1;
+ }
+ }
+#endif
+}
+
+/* 3. Tuning rcvbuf, when connection enters established state. */
+
+static void tcp_fixup_rcvbuf(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int rcvmem = tp->advmss+MAX_TCP_HEADER+16+sizeof(struct sk_buff);
+
+ /* Try to select rcvbuf so that 4 mss-sized segments
+ * will fit to window and correspoding skbs will fit to our rcvbuf.
+ * (was 3; 4 is minimum to allow fast retransmit to work.)
+ */
+ while (tcp_win_from_space(rcvmem) < tp->advmss)
+ rcvmem += 128;
+ if (sk->rcvbuf < 4*rcvmem)
+ sk->rcvbuf = min(4*rcvmem, sysctl_tcp_rmem[2]);
+#endif
+}
+
+/* 4. Try to fixup all. It is made iimediately after connection enters
+ * established state.
+ */
+static void tcp_init_buffer_space(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int maxwin;
+
+ if (!(sk->userlocks&SOCK_RCVBUF_LOCK))
+ tcp_fixup_rcvbuf(sk);
+ if (!(sk->userlocks&SOCK_SNDBUF_LOCK))
+ tcp_fixup_sndbuf(sk);
+
+ maxwin = tcp_full_space(sk);
+
+ if (tp->window_clamp >= maxwin) {
+ tp->window_clamp = maxwin;
+
+ if (sysctl_tcp_app_win && maxwin>4*tp->advmss)
+ tp->window_clamp = max(maxwin-(maxwin>>sysctl_tcp_app_win), 4*tp->advmss);
+ }
+
+ /* Force reservation of one segment. */
+ if (sysctl_tcp_app_win &&
+ tp->window_clamp > 2*tp->advmss &&
+ tp->window_clamp + tp->advmss > maxwin)
+ tp->window_clamp = max(2*tp->advmss, maxwin-tp->advmss);
+
+ tp->rcv_ssthresh = min(tp->rcv_ssthresh, tp->window_clamp);
+ tp->snd_cwnd_stamp = tcp_time_stamp;
+#endif
+}
+
+/* 5. Recalculate window clamp after socket hit its memory bounds. */
+static void tcp_clamp_window(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+ struct sk_buff *skb;
+ unsigned int app_win = tp->rcv_nxt - tp->copied_seq;
+ int ofo_win = 0;
+
+ tp->ack.quick = 0;
+
+ skb_queue_walk(&tp->out_of_order_queue, skb) {
+ ofo_win += skb->len;
+ }
+
+ /* If overcommit is due to out of order segments,
+ * do not clamp window. Try to expand rcvbuf instead.
+ */
+ if (ofo_win) {
+ if (sk->rcvbuf < sysctl_tcp_rmem[2] &&
+ !(sk->userlocks&SOCK_RCVBUF_LOCK) &&
+ !tcp_memory_pressure &&
+ atomic_read(&tcp_memory_allocated) < sysctl_tcp_mem[0])
+ sk->rcvbuf = min(atomic_read(&sk->rmem_alloc), sysctl_tcp_rmem[2]);
+ }
+ if (atomic_read(&sk->rmem_alloc) > sk->rcvbuf) {
+ app_win += ofo_win;
+ if (atomic_read(&sk->rmem_alloc) >= 2*sk->rcvbuf)
+ app_win >>= 1;
+ if (app_win > tp->ack.rcv_mss)
+ app_win -= tp->ack.rcv_mss;
+ app_win = max(app_win, 2U*tp->advmss);
+
+ if (!ofo_win)
+ tp->window_clamp = min(tp->window_clamp, app_win);
+ tp->rcv_ssthresh = min(tp->window_clamp, 2U*tp->advmss);
+ }
+#endif
+}
+
+/* There is something which you must keep in mind when you analyze the
+ * behavior of the tp->ato delayed ack timeout interval. When a
+ * connection starts up, we want to ack as quickly as possible. The
+ * problem is that "good" TCP's do slow start at the beginning of data
+ * transmission. The means that until we send the first few ACK's the
+ * sender will sit on his end and only queue most of his data, because
+ * he can only send snd_cwnd unacked packets at any given time. For
+ * each ACK we send, he increments snd_cwnd and transmits more of his
+ * queue. -DaveM
+ */
+static void tcp_event_data_recv(struct sock *sk, struct tcp_opt *tp, struct sk_buff *skb)
+{
+#if 0
+ u32 now;
+
+ tcp_schedule_ack(tp);
+
+ tcp_measure_rcv_mss(tp, skb);
+
+ now = tcp_time_stamp;
+
+ if (!tp->ack.ato) {
+ /* The _first_ data packet received, initialize
+ * delayed ACK engine.
+ */
+ tcp_incr_quickack(tp);
+ tp->ack.ato = TCP_ATO_MIN;
+ } else {
+ int m = now - tp->ack.lrcvtime;
+
+ if (m <= TCP_ATO_MIN/2) {
+ /* The fastest case is the first. */
+ tp->ack.ato = (tp->ack.ato>>1) + TCP_ATO_MIN/2;
+ } else if (m < tp->ack.ato) {
+ tp->ack.ato = (tp->ack.ato>>1) + m;
+ if (tp->ack.ato > tp->rto)
+ tp->ack.ato = tp->rto;
+ } else if (m > tp->rto) {
+ /* Too long gap. Apparently sender falled to
+ * restart window, so that we send ACKs quickly.
+ */
+ tcp_incr_quickack(tp);
+ tcp_mem_reclaim(sk);
+ }
+ }
+ tp->ack.lrcvtime = now;
+
+ TCP_ECN_check_ce(tp, skb);
+
+ if (skb->len >= 128)
+ tcp_grow_window(sk, tp, skb);
+#endif
+}
+
+/* Called to compute a smoothed rtt estimate. The data fed to this
+ * routine either comes from timestamps, or from segments that were
+ * known _not_ to have been retransmitted [see Karn/Partridge
+ * Proceedings SIGCOMM 87]. The algorithm is from the SIGCOMM 88
+ * piece by Van Jacobson.
+ * NOTE: the next three routines used to be one big routine.
+ * To save cycles in the RFC 1323 implementation it was better to break
+ * it up into three procedures. -- erics
+ */
+static __inline__ void tcp_rtt_estimator(struct tcp_opt *tp, __u32 mrtt)
+{
+#if 0
+ long m = mrtt; /* RTT */
+
+ /* The following amusing code comes from Jacobson's
+ * article in SIGCOMM '88. Note that rtt and mdev
+ * are scaled versions of rtt and mean deviation.
+ * This is designed to be as fast as possible
+ * m stands for "measurement".
+ *
+ * On a 1990 paper the rto value is changed to:
+ * RTO = rtt + 4 * mdev
+ *
+ * Funny. This algorithm seems to be very broken.
+ * These formulae increase RTO, when it should be decreased, increase
+ * too slowly, when it should be incresed fastly, decrease too fastly
+ * etc. I guess in BSD RTO takes ONE value, so that it is absolutely
+ * does not matter how to _calculate_ it. Seems, it was trap
+ * that VJ failed to avoid. 8)
+ */
+ if(m == 0)
+ m = 1;
+ if (tp->srtt != 0) {
+ m -= (tp->srtt >> 3); /* m is now error in rtt est */
+ tp->srtt += m; /* rtt = 7/8 rtt + 1/8 new */
+ if (m < 0) {
+ m = -m; /* m is now abs(error) */
+ m -= (tp->mdev >> 2); /* similar update on mdev */
+ /* This is similar to one of Eifel findings.
+ * Eifel blocks mdev updates when rtt decreases.
+ * This solution is a bit different: we use finer gain
+ * for mdev in this case (alpha*beta).
+ * Like Eifel it also prevents growth of rto,
+ * but also it limits too fast rto decreases,
+ * happening in pure Eifel.
+ */
+ if (m > 0)
+ m >>= 3;
+ } else {
+ m -= (tp->mdev >> 2); /* similar update on mdev */
+ }
+ tp->mdev += m; /* mdev = 3/4 mdev + 1/4 new */
+ if (tp->mdev > tp->mdev_max) {
+ tp->mdev_max = tp->mdev;
+ if (tp->mdev_max > tp->rttvar)
+ tp->rttvar = tp->mdev_max;
+ }
+ if (after(tp->snd_una, tp->rtt_seq)) {
+ if (tp->mdev_max < tp->rttvar)
+ tp->rttvar -= (tp->rttvar-tp->mdev_max)>>2;
+ tp->rtt_seq = tp->snd_nxt;
+ tp->mdev_max = TCP_RTO_MIN;
+ }
+ } else {
+ /* no previous measure. */
+ tp->srtt = m<<3; /* take the measured time to be rtt */
+ tp->mdev = m<<1; /* make sure rto = 3*rtt */
+ tp->mdev_max = tp->rttvar = max(tp->mdev, TCP_RTO_MIN);
+ tp->rtt_seq = tp->snd_nxt;
+ }
+#endif
+}
+
+/* Calculate rto without backoff. This is the second half of Van Jacobson's
+ * routine referred to above.
+ */
+static __inline__ void tcp_set_rto(struct tcp_opt *tp)
+{
+#if 0
+ /* Old crap is replaced with new one. 8)
+ *
+ * More seriously:
+ * 1. If rtt variance happened to be less 50msec, it is hallucination.
+ * It cannot be less due to utterly erratic ACK generation made
+ * at least by solaris and freebsd. "Erratic ACKs" has _nothing_
+ * to do with delayed acks, because at cwnd>2 true delack timeout
+ * is invisible. Actually, Linux-2.4 also generates erratic
+ * ACKs in some curcumstances.
+ */
+ tp->rto = (tp->srtt >> 3) + tp->rttvar;
+
+ /* 2. Fixups made earlier cannot be right.
+ * If we do not estimate RTO correctly without them,
+ * all the algo is pure shit and should be replaced
+ * with correct one. It is exaclty, which we pretend to do.
+ */
+#endif
+}
+
+/* NOTE: clamping at TCP_RTO_MIN is not required, current algo
+ * guarantees that rto is higher.
+ */
+static __inline__ void tcp_bound_rto(struct tcp_opt *tp)
+{
+#if 0
+ if (tp->rto > TCP_RTO_MAX)
+ tp->rto = TCP_RTO_MAX;
+#endif
+}
+
+/* Save metrics learned by this TCP session.
+ This function is called only, when TCP finishes successfully
+ i.e. when it enters TIME-WAIT or goes from LAST-ACK to CLOSE.
+ */
+void tcp_update_metrics(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct dst_entry *dst = __sk_dst_get(sk);
+
+ dst_confirm(dst);
+
+ if (dst && (dst->flags&DST_HOST)) {
+ int m;
+
+ if (tp->backoff || !tp->srtt) {
+ /* This session failed to estimate rtt. Why?
+ * Probably, no packets returned in time.
+ * Reset our results.
+ */
+ if (!(dst->mxlock&(1<<RTAX_RTT)))
+ dst->rtt = 0;
+ return;
+ }
+
+ m = dst->rtt - tp->srtt;
+
+ /* If newly calculated rtt larger than stored one,
+ * store new one. Otherwise, use EWMA. Remember,
+ * rtt overestimation is always better than underestimation.
+ */
+ if (!(dst->mxlock&(1<<RTAX_RTT))) {
+ if (m <= 0)
+ dst->rtt = tp->srtt;
+ else
+ dst->rtt -= (m>>3);
+ }
+
+ if (!(dst->mxlock&(1<<RTAX_RTTVAR))) {
+ if (m < 0)
+ m = -m;
+
+ /* Scale deviation to rttvar fixed point */
+ m >>= 1;
+ if (m < tp->mdev)
+ m = tp->mdev;
+
+ if (m >= dst->rttvar)
+ dst->rttvar = m;
+ else
+ dst->rttvar -= (dst->rttvar - m)>>2;
+ }
+
+ if (tp->snd_ssthresh >= 0xFFFF) {
+ /* Slow start still did not finish. */
+ if (dst->ssthresh &&
+ !(dst->mxlock&(1<<RTAX_SSTHRESH)) &&
+ (tp->snd_cwnd>>1) > dst->ssthresh)
+ dst->ssthresh = (tp->snd_cwnd>>1);
+ if (!(dst->mxlock&(1<<RTAX_CWND)) &&
+ tp->snd_cwnd > dst->cwnd)
+ dst->cwnd = tp->snd_cwnd;
+ } else if (tp->snd_cwnd > tp->snd_ssthresh &&
+ tp->ca_state == TCP_CA_Open) {
+ /* Cong. avoidance phase, cwnd is reliable. */
+ if (!(dst->mxlock&(1<<RTAX_SSTHRESH)))
+ dst->ssthresh = max(tp->snd_cwnd>>1, tp->snd_ssthresh);
+ if (!(dst->mxlock&(1<<RTAX_CWND)))
+ dst->cwnd = (dst->cwnd + tp->snd_cwnd)>>1;
+ } else {
+ /* Else slow start did not finish, cwnd is non-sense,
+ ssthresh may be also invalid.
+ */
+ if (!(dst->mxlock&(1<<RTAX_CWND)))
+ dst->cwnd = (dst->cwnd + tp->snd_ssthresh)>>1;
+ if (dst->ssthresh &&
+ !(dst->mxlock&(1<<RTAX_SSTHRESH)) &&
+ tp->snd_ssthresh > dst->ssthresh)
+ dst->ssthresh = tp->snd_ssthresh;
+ }
+
+ if (!(dst->mxlock&(1<<RTAX_REORDERING))) {
+ if (dst->reordering < tp->reordering &&
+ tp->reordering != sysctl_tcp_reordering)
+ dst->reordering = tp->reordering;
+ }
+ }
+#endif
+}
+
+/* Increase initial CWND conservatively: if estimated
+ * RTT is low enough (<20msec) or if we have some preset ssthresh.
+ *
+ * Numbers are taken from RFC2414.
+ */
+__u32 tcp_init_cwnd(struct tcp_opt *tp)
+{
+#if 0
+ __u32 cwnd;
+
+ if (tp->mss_cache > 1460)
+ return 2;
+
+ cwnd = (tp->mss_cache > 1095) ? 3 : 4;
+
+ if (!tp->srtt || (tp->snd_ssthresh >= 0xFFFF && tp->srtt > ((HZ/50)<<3)))
+ cwnd = 2;
+ else if (cwnd > tp->snd_ssthresh)
+ cwnd = tp->snd_ssthresh;
+
+ return min_t(__u32, cwnd, tp->snd_cwnd_clamp);
+#else
+ return 0;
+#endif
+}
+
+/* Initialize metrics on socket. */
+
+static void tcp_init_metrics(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct dst_entry *dst = __sk_dst_get(sk);
+
+ if (dst == NULL)
+ goto reset;
+
+ dst_confirm(dst);
+
+ if (dst->mxlock&(1<<RTAX_CWND))
+ tp->snd_cwnd_clamp = dst->cwnd;
+ if (dst->ssthresh) {
+ tp->snd_ssthresh = dst->ssthresh;
+ if (tp->snd_ssthresh > tp->snd_cwnd_clamp)
+ tp->snd_ssthresh = tp->snd_cwnd_clamp;
+ }
+ if (dst->reordering && tp->reordering != dst->reordering) {
+ tp->sack_ok &= ~2;
+ tp->reordering = dst->reordering;
+ }
+
+ if (dst->rtt == 0)
+ goto reset;
+
+ if (!tp->srtt && dst->rtt < (TCP_TIMEOUT_INIT<<3))
+ goto reset;
+
+ /* Initial rtt is determined from SYN,SYN-ACK.
+ * The segment is small and rtt may appear much
+ * less than real one. Use per-dst memory
+ * to make it more realistic.
+ *
+ * A bit of theory. RTT is time passed after "normal" sized packet
+ * is sent until it is ACKed. In normal curcumstances sending small
+ * packets force peer to delay ACKs and calculation is correct too.
+ * The algorithm is adaptive and, provided we follow specs, it
+ * NEVER underestimate RTT. BUT! If peer tries to make some clever
+ * tricks sort of "quick acks" for time long enough to decrease RTT
+ * to low value, and then abruptly stops to do it and starts to delay
+ * ACKs, wait for troubles.
+ */
+ if (dst->rtt > tp->srtt)
+ tp->srtt = dst->rtt;
+ if (dst->rttvar > tp->mdev) {
+ tp->mdev = dst->rttvar;
+ tp->mdev_max = tp->rttvar = max(tp->mdev, TCP_RTO_MIN);
+ }
+ tcp_set_rto(tp);
+ tcp_bound_rto(tp);
+ if (tp->rto < TCP_TIMEOUT_INIT && !tp->saw_tstamp)
+ goto reset;
+ tp->snd_cwnd = tcp_init_cwnd(tp);
+ tp->snd_cwnd_stamp = tcp_time_stamp;
+ return;
+
+reset:
+ /* Play conservative. If timestamps are not
+ * supported, TCP will fail to recalculate correct
+ * rtt, if initial rto is too small. FORGET ALL AND RESET!
+ */
+ if (!tp->saw_tstamp && tp->srtt) {
+ tp->srtt = 0;
+ tp->mdev = tp->mdev_max = tp->rttvar = TCP_TIMEOUT_INIT;
+ tp->rto = TCP_TIMEOUT_INIT;
+ }
+#endif
+}
+
+static void tcp_update_reordering(struct tcp_opt *tp, int metric, int ts)
+{
+#if 0
+ if (metric > tp->reordering) {
+ tp->reordering = min(TCP_MAX_REORDERING, metric);
+
+ /* This exciting event is worth to be remembered. 8) */
+ if (ts)
+ NET_INC_STATS_BH(TCPTSReorder);
+ else if (IsReno(tp))
+ NET_INC_STATS_BH(TCPRenoReorder);
+ else if (IsFack(tp))
+ NET_INC_STATS_BH(TCPFACKReorder);
+ else
+ NET_INC_STATS_BH(TCPSACKReorder);
+#if FASTRETRANS_DEBUG > 1
+ printk(KERN_DEBUG "Disorder%d %d %u f%u s%u rr%d\n",
+ tp->sack_ok, tp->ca_state,
+ tp->reordering, tp->fackets_out, tp->sacked_out,
+ tp->undo_marker ? tp->undo_retrans : 0);
+#endif
+ /* Disable FACK yet. */
+ tp->sack_ok &= ~2;
+ }
+#endif
+}
+
+/* This procedure tags the retransmission queue when SACKs arrive.
+ *
+ * We have three tag bits: SACKED(S), RETRANS(R) and LOST(L).
+ * Packets in queue with these bits set are counted in variables
+ * sacked_out, retrans_out and lost_out, correspondingly.
+ *
+ * Valid combinations are:
+ * Tag InFlight Description
+ * 0 1 - orig segment is in flight.
+ * S 0 - nothing flies, orig reached receiver.
+ * L 0 - nothing flies, orig lost by net.
+ * R 2 - both orig and retransmit are in flight.
+ * L|R 1 - orig is lost, retransmit is in flight.
+ * S|R 1 - orig reached receiver, retrans is still in flight.
+ * (L|S|R is logically valid, it could occur when L|R is sacked,
+ * but it is equivalent to plain S and code short-curcuits it to S.
+ * L|S is logically invalid, it would mean -1 packet in flight 8))
+ *
+ * These 6 states form finite state machine, controlled by the following events:
+ * 1. New ACK (+SACK) arrives. (tcp_sacktag_write_queue())
+ * 2. Retransmission. (tcp_retransmit_skb(), tcp_xmit_retransmit_queue())
+ * 3. Loss detection event of one of three flavors:
+ * A. Scoreboard estimator decided the packet is lost.
+ * A'. Reno "three dupacks" marks head of queue lost.
+ * A''. Its FACK modfication, head until snd.fack is lost.
+ * B. SACK arrives sacking data transmitted after never retransmitted
+ * hole was sent out.
+ * C. SACK arrives sacking SND.NXT at the moment, when the
+ * segment was retransmitted.
+ * 4. D-SACK added new rule: D-SACK changes any tag to S.
+ *
+ * It is pleasant to note, that state diagram turns out to be commutative,
+ * so that we are allowed not to be bothered by order of our actions,
+ * when multiple events arrive simultaneously. (see the function below).
+ *
+ * Reordering detection.
+ * --------------------
+ * Reordering metric is maximal distance, which a packet can be displaced
+ * in packet stream. With SACKs we can estimate it:
+ *
+ * 1. SACK fills old hole and the corresponding segment was not
+ * ever retransmitted -> reordering. Alas, we cannot use it
+ * when segment was retransmitted.
+ * 2. The last flaw is solved with D-SACK. D-SACK arrives
+ * for retransmitted and already SACKed segment -> reordering..
+ * Both of these heuristics are not used in Loss state, when we cannot
+ * account for retransmits accurately.
+ */
+static int
+tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_una)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ unsigned char *ptr = ack_skb->h.raw + TCP_SKB_CB(ack_skb)->sacked;
+ struct tcp_sack_block *sp = (struct tcp_sack_block *)(ptr+2);
+ int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3;
+ int reord = tp->packets_out;
+ int prior_fackets;
+ u32 lost_retrans = 0;
+ int flag = 0;
+ int i;
+
+ if (!tp->sacked_out)
+ tp->fackets_out = 0;
+ prior_fackets = tp->fackets_out;
+
+ for (i=0; i<num_sacks; i++, sp++) {
+ struct sk_buff *skb;
+ __u32 start_seq = ntohl(sp->start_seq);
+ __u32 end_seq = ntohl(sp->end_seq);
+ int fack_count = 0;
+ int dup_sack = 0;
+
+ /* Check for D-SACK. */
+ if (i == 0) {
+ u32 ack = TCP_SKB_CB(ack_skb)->ack_seq;
+
+ if (before(start_seq, ack)) {
+ dup_sack = 1;
+ tp->sack_ok |= 4;
+ NET_INC_STATS_BH(TCPDSACKRecv);
+ } else if (num_sacks > 1 &&
+ !after(end_seq, ntohl(sp[1].end_seq)) &&
+ !before(start_seq, ntohl(sp[1].start_seq))) {
+ dup_sack = 1;
+ tp->sack_ok |= 4;
+ NET_INC_STATS_BH(TCPDSACKOfoRecv);
+ }
+
+ /* D-SACK for already forgotten data...
+ * Do dumb counting. */
+ if (dup_sack &&
+ !after(end_seq, prior_snd_una) &&
+ after(end_seq, tp->undo_marker))
+ tp->undo_retrans--;
+
+ /* Eliminate too old ACKs, but take into
+ * account more or less fresh ones, they can
+ * contain valid SACK info.
+ */
+ if (before(ack, prior_snd_una-tp->max_window))
+ return 0;
+ }
+
+ /* Event "B" in the comment above. */
+ if (after(end_seq, tp->high_seq))
+ flag |= FLAG_DATA_LOST;
+
+ for_retrans_queue(skb, sk, tp) {
+ u8 sacked = TCP_SKB_CB(skb)->sacked;
+ int in_sack;
+
+ /* The retransmission queue is always in order, so
+ * we can short-circuit the walk early.
+ */
+ if(!before(TCP_SKB_CB(skb)->seq, end_seq))
+ break;
+
+ fack_count++;
+
+ in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) &&
+ !before(end_seq, TCP_SKB_CB(skb)->end_seq);
+
+ /* Account D-SACK for retransmitted packet. */
+ if ((dup_sack && in_sack) &&
+ (sacked & TCPCB_RETRANS) &&
+ after(TCP_SKB_CB(skb)->end_seq, tp->undo_marker))
+ tp->undo_retrans--;
+
+ /* The frame is ACKed. */
+ if (!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una)) {
+ if (sacked&TCPCB_RETRANS) {
+ if ((dup_sack && in_sack) &&
+ (sacked&TCPCB_SACKED_ACKED))
+ reord = min(fack_count, reord);
+ } else {
+ /* If it was in a hole, we detected reordering. */
+ if (fack_count < prior_fackets &&
+ !(sacked&TCPCB_SACKED_ACKED))
+ reord = min(fack_count, reord);
+ }
+
+ /* Nothing to do; acked frame is about to be dropped. */
+ continue;
+ }
+
+ if ((sacked&TCPCB_SACKED_RETRANS) &&
+ after(end_seq, TCP_SKB_CB(skb)->ack_seq) &&
+ (!lost_retrans || after(end_seq, lost_retrans)))
+ lost_retrans = end_seq;
+
+ if (!in_sack)
+ continue;
+
+ if (!(sacked&TCPCB_SACKED_ACKED)) {
+ if (sacked & TCPCB_SACKED_RETRANS) {
+ /* If the segment is not tagged as lost,
+ * we do not clear RETRANS, believing
+ * that retransmission is still in flight.
+ */
+ if (sacked & TCPCB_LOST) {
+ TCP_SKB_CB(skb)->sacked &= ~(TCPCB_LOST|TCPCB_SACKED_RETRANS);
+ tp->lost_out--;
+ tp->retrans_out--;
+ }
+ } else {
+ /* New sack for not retransmitted frame,
+ * which was in hole. It is reordering.
+ */
+ if (!(sacked & TCPCB_RETRANS) &&
+ fack_count < prior_fackets)
+ reord = min(fack_count, reord);
+
+ if (sacked & TCPCB_LOST) {
+ TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
+ tp->lost_out--;
+ }
+ }
+
+ TCP_SKB_CB(skb)->sacked |= TCPCB_SACKED_ACKED;
+ flag |= FLAG_DATA_SACKED;
+ tp->sacked_out++;
+
+ if (fack_count > tp->fackets_out)
+ tp->fackets_out = fack_count;
+ } else {
+ if (dup_sack && (sacked&TCPCB_RETRANS))
+ reord = min(fack_count, reord);
+ }
+
+ /* D-SACK. We can detect redundant retransmission
+ * in S|R and plain R frames and clear it.
+ * undo_retrans is decreased above, L|R frames
+ * are accounted above as well.
+ */
+ if (dup_sack &&
+ (TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_RETRANS)) {
+ TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
+ tp->retrans_out--;
+ }
+ }
+ }
+
+ /* Check for lost retransmit. This superb idea is
+ * borrowed from "ratehalving". Event "C".
+ * Later note: FACK people cheated me again 8),
+ * we have to account for reordering! Ugly,
+ * but should help.
+ */
+ if (lost_retrans && tp->ca_state == TCP_CA_Recovery) {
+ struct sk_buff *skb;
+
+ for_retrans_queue(skb, sk, tp) {
+ if (after(TCP_SKB_CB(skb)->seq, lost_retrans))
+ break;
+ if (!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una))
+ continue;
+ if ((TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_RETRANS) &&
+ after(lost_retrans, TCP_SKB_CB(skb)->ack_seq) &&
+ (IsFack(tp) ||
+ !before(lost_retrans, TCP_SKB_CB(skb)->ack_seq+tp->reordering*tp->mss_cache))) {
+ TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
+ tp->retrans_out--;
+
+ if (!(TCP_SKB_CB(skb)->sacked&(TCPCB_LOST|TCPCB_SACKED_ACKED))) {
+ tp->lost_out++;
+ TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
+ flag |= FLAG_DATA_SACKED;
+ NET_INC_STATS_BH(TCPLostRetransmit);
+ }
+ }
+ }
+ }
+
+ tp->left_out = tp->sacked_out + tp->lost_out;
+
+ if (reord < tp->fackets_out && tp->ca_state != TCP_CA_Loss)
+ tcp_update_reordering(tp, (tp->fackets_out+1)-reord, 0);
+
+#if FASTRETRANS_DEBUG > 0
+ BUG_TRAP((int)tp->sacked_out >= 0);
+ BUG_TRAP((int)tp->lost_out >= 0);
+ BUG_TRAP((int)tp->retrans_out >= 0);
+ BUG_TRAP((int)tcp_packets_in_flight(tp) >= 0);
+#endif
+ return flag;
+#else
+ return 0;
+#endif
+}
+
+void tcp_clear_retrans(struct tcp_opt *tp)
+{
+#if 0
+ tp->left_out = 0;
+ tp->retrans_out = 0;
+
+ tp->fackets_out = 0;
+ tp->sacked_out = 0;
+ tp->lost_out = 0;
+
+ tp->undo_marker = 0;
+ tp->undo_retrans = 0;
+#endif
+}
+
+/* Enter Loss state. If "how" is not zero, forget all SACK information
+ * and reset tags completely, otherwise preserve SACKs. If receiver
+ * dropped its ofo queue, we will know this due to reneging detection.
+ */
+void tcp_enter_loss(struct sock *sk, int how)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ struct sk_buff *skb;
+ int cnt = 0;
+
+ /* Reduce ssthresh if it has not yet been made inside this window. */
+ if (tp->ca_state <= TCP_CA_Disorder ||
+ tp->snd_una == tp->high_seq ||
+ (tp->ca_state == TCP_CA_Loss && !tp->retransmits)) {
+ tp->prior_ssthresh = tcp_current_ssthresh(tp);
+ tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
+ }
+ tp->snd_cwnd = 1;
+ tp->snd_cwnd_cnt = 0;
+ tp->snd_cwnd_stamp = tcp_time_stamp;
+
+ tcp_clear_retrans(tp);
+
+ /* Push undo marker, if it was plain RTO and nothing
+ * was retransmitted. */
+ if (!how)
+ tp->undo_marker = tp->snd_una;
+
+ for_retrans_queue(skb, sk, tp) {
+ cnt++;
+ if (TCP_SKB_CB(skb)->sacked&TCPCB_RETRANS)
+ tp->undo_marker = 0;
+ TCP_SKB_CB(skb)->sacked &= (~TCPCB_TAGBITS)|TCPCB_SACKED_ACKED;
+ if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED) || how) {
+ TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED;
+ TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
+ tp->lost_out++;
+ } else {
+ tp->sacked_out++;
+ tp->fackets_out = cnt;
+ }
+ }
+ tcp_sync_left_out(tp);
+
+ tp->reordering = min_t(unsigned int, tp->reordering, sysctl_tcp_reordering);
+ tp->ca_state = TCP_CA_Loss;
+ tp->high_seq = tp->snd_nxt;
+ TCP_ECN_queue_cwr(tp);
+#endif
+}
+
+static int tcp_check_sack_reneging(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+ struct sk_buff *skb;
+
+ /* If ACK arrived pointing to a remembered SACK,
+ * it means that our remembered SACKs do not reflect
+ * real state of receiver i.e.
+ * receiver _host_ is heavily congested (or buggy).
+ * Do processing similar to RTO timeout.
+ */
+ if ((skb = skb_peek(&sk->write_queue)) != NULL &&
+ (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) {
+ NET_INC_STATS_BH(TCPSACKReneging);
+
+ tcp_enter_loss(sk, 1);
+ tp->retransmits++;
+ tcp_retransmit_skb(sk, skb_peek(&sk->write_queue));
+ tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+ return 1;
+ }
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+static inline int tcp_fackets_out(struct tcp_opt *tp)
+{
+#if 0
+ return IsReno(tp) ? tp->sacked_out+1 : tp->fackets_out;
+#else
+ return 0;
+#endif
+}
+
+static inline int tcp_skb_timedout(struct tcp_opt *tp, struct sk_buff *skb)
+{
+#if 0
+ return (tcp_time_stamp - TCP_SKB_CB(skb)->when > tp->rto);
+#else
+ return 0;
+#endif
+}
+
+static inline int tcp_head_timedout(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+ return tp->packets_out && tcp_skb_timedout(tp, skb_peek(&sk->write_queue));
+#else
+ return 0;
+#endif
+}
+
+/* Linux NewReno/SACK/FACK/ECN state machine.
+ * --------------------------------------
+ *
+ * "Open" Normal state, no dubious events, fast path.
+ * "Disorder" In all the respects it is "Open",
+ * but requires a bit more attention. It is entered when
+ * we see some SACKs or dupacks. It is split of "Open"
+ * mainly to move some processing from fast path to slow one.
+ * "CWR" CWND was reduced due to some Congestion Notification event.
+ * It can be ECN, ICMP source quench, local device congestion.
+ * "Recovery" CWND was reduced, we are fast-retransmitting.
+ * "Loss" CWND was reduced due to RTO timeout or SACK reneging.
+ *
+ * tcp_fastretrans_alert() is entered:
+ * - each incoming ACK, if state is not "Open"
+ * - when arrived ACK is unusual, namely:
+ * * SACK
+ * * Duplicate ACK.
+ * * ECN ECE.
+ *
+ * Counting packets in flight is pretty simple.
+ *
+ * in_flight = packets_out - left_out + retrans_out
+ *
+ * packets_out is SND.NXT-SND.UNA counted in packets.
+ *
+ * retrans_out is number of retransmitted segments.
+ *
+ * left_out is number of segments left network, but not ACKed yet.
+ *
+ * left_out = sacked_out + lost_out
+ *
+ * sacked_out: Packets, which arrived to receiver out of order
+ * and hence not ACKed. With SACKs this number is simply
+ * amount of SACKed data. Even without SACKs
+ * it is easy to give pretty reliable estimate of this number,
+ * counting duplicate ACKs.
+ *
+ * lost_out: Packets lost by network. TCP has no explicit
+ * "loss notification" feedback from network (for now).
+ * It means that this number can be only _guessed_.
+ * Actually, it is the heuristics to predict lossage that
+ * distinguishes different algorithms.
+ *
+ * F.e. after RTO, when all the queue is considered as lost,
+ * lost_out = packets_out and in_flight = retrans_out.
+ *
+ * Essentially, we have now two algorithms counting
+ * lost packets.
+ *
+ * FACK: It is the simplest heuristics. As soon as we decided
+ * that something is lost, we decide that _all_ not SACKed
+ * packets until the most forward SACK are lost. I.e.
+ * lost_out = fackets_out - sacked_out and left_out = fackets_out.
+ * It is absolutely correct estimate, if network does not reorder
+ * packets. And it loses any connection to reality when reordering
+ * takes place. We use FACK by default until reordering
+ * is suspected on the path to this destination.
+ *
+ * NewReno: when Recovery is entered, we assume that one segment
+ * is lost (classic Reno). While we are in Recovery and
+ * a partial ACK arrives, we assume that one more packet
+ * is lost (NewReno). This heuristics are the same in NewReno
+ * and SACK.
+ *
+ * Imagine, that's all! Forget about all this shamanism about CWND inflation
+ * deflation etc. CWND is real congestion window, never inflated, changes
+ * only according to classic VJ rules.
+ *
+ * Really tricky (and requiring careful tuning) part of algorithm
+ * is hidden in functions tcp_time_to_recover() and tcp_xmit_retransmit_queue().
+ * The first determines the moment _when_ we should reduce CWND and,
+ * hence, slow down forward transmission. In fact, it determines the moment
+ * when we decide that hole is caused by loss, rather than by a reorder.
+ *
+ * tcp_xmit_retransmit_queue() decides, _what_ we should retransmit to fill
+ * holes, caused by lost packets.
+ *
+ * And the most logically complicated part of algorithm is undo
+ * heuristics. We detect false retransmits due to both too early
+ * fast retransmit (reordering) and underestimated RTO, analyzing
+ * timestamps and D-SACKs. When we detect that some segments were
+ * retransmitted by mistake and CWND reduction was wrong, we undo
+ * window reduction and abort recovery phase. This logic is hidden
+ * inside several functions named tcp_try_undo_<something>.
+ */
+
+/* This function decides, when we should leave Disordered state
+ * and enter Recovery phase, reducing congestion window.
+ *
+ * Main question: may we further continue forward transmission
+ * with the same cwnd?
+ */
+static int
+tcp_time_to_recover(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+ /* Trick#1: The loss is proven. */
+ if (tp->lost_out)
+ return 1;
+
+ /* Not-A-Trick#2 : Classic rule... */
+ if (tcp_fackets_out(tp) > tp->reordering)
+ return 1;
+
+ /* Trick#3 : when we use RFC2988 timer restart, fast
+ * retransmit can be triggered by timeout of queue head.
+ */
+ if (tcp_head_timedout(sk, tp))
+ return 1;
+
+ /* Trick#4: It is still not OK... But will it be useful to delay
+ * recovery more?
+ */
+ if (tp->packets_out <= tp->reordering &&
+ tp->sacked_out >= max_t(__u32, tp->packets_out/2, sysctl_tcp_reordering) &&
+ !tcp_may_send_now(sk, tp)) {
+ /* We have nothing to send. This connection is limited
+ * either by receiver window or by application.
+ */
+ return 1;
+ }
+
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+/* If we receive more dupacks than we expected counting segments
+ * in assumption of absent reordering, interpret this as reordering.
+ * The only another reason could be bug in receiver TCP.
+ */
+static void tcp_check_reno_reordering(struct tcp_opt *tp, int addend)
+{
+#if 0
+ u32 holes;
+
+ holes = max(tp->lost_out, 1U);
+ holes = min(holes, tp->packets_out);
+
+ if (tp->sacked_out + holes > tp->packets_out) {
+ tp->sacked_out = tp->packets_out - holes;
+ tcp_update_reordering(tp, tp->packets_out+addend, 0);
+ }
+#endif
+}
+
+/* Emulate SACKs for SACKless connection: account for a new dupack. */
+
+static void tcp_add_reno_sack(struct tcp_opt *tp)
+{
+#if 0
+ ++tp->sacked_out;
+ tcp_check_reno_reordering(tp, 0);
+ tcp_sync_left_out(tp);
+#endif
+}
+
+/* Account for ACK, ACKing some data in Reno Recovery phase. */
+
+static void tcp_remove_reno_sacks(struct sock *sk, struct tcp_opt *tp, int acked)
+{
+#if 0
+ if (acked > 0) {
+ /* One ACK acked hole. The rest eat duplicate ACKs. */
+ if (acked-1 >= tp->sacked_out)
+ tp->sacked_out = 0;
+ else
+ tp->sacked_out -= acked-1;
+ }
+ tcp_check_reno_reordering(tp, acked);
+ tcp_sync_left_out(tp);
+#endif
+}
+
+static inline void tcp_reset_reno_sack(struct tcp_opt *tp)
+{
+#if 0
+ tp->sacked_out = 0;
+ tp->left_out = tp->lost_out;
+#endif
+}
+
+/* Mark head of queue up as lost. */
+static void
+tcp_mark_head_lost(struct sock *sk, struct tcp_opt *tp, int packets, u32 high_seq)
+{
+#if 0
+ struct sk_buff *skb;
+ int cnt = packets;
+
+ BUG_TRAP(cnt <= tp->packets_out);
+
+ for_retrans_queue(skb, sk, tp) {
+ if (--cnt < 0 || after(TCP_SKB_CB(skb)->end_seq, high_seq))
+ break;
+ if (!(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) {
+ TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
+ tp->lost_out++;
+ }
+ }
+ tcp_sync_left_out(tp);
+#endif
+}
+
+/* Account newly detected lost packet(s) */
+
+static void tcp_update_scoreboard(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+ if (IsFack(tp)) {
+ int lost = tp->fackets_out - tp->reordering;
+ if (lost <= 0)
+ lost = 1;
+ tcp_mark_head_lost(sk, tp, lost, tp->high_seq);
+ } else {
+ tcp_mark_head_lost(sk, tp, 1, tp->high_seq);
+ }
+
+ /* New heuristics: it is possible only after we switched
+ * to restart timer each time when something is ACKed.
+ * Hence, we can detect timed out packets during fast
+ * retransmit without falling to slow start.
+ */
+ if (tcp_head_timedout(sk, tp)) {
+ struct sk_buff *skb;
+
+ for_retrans_queue(skb, sk, tp) {
+ if (tcp_skb_timedout(tp, skb) &&
+ !(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) {
+ TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
+ tp->lost_out++;
+ }
+ }
+ tcp_sync_left_out(tp);
+ }
+#endif
+}
+
+/* CWND moderation, preventing bursts due to too big ACKs
+ * in dubious situations.
+ */
+static __inline__ void tcp_moderate_cwnd(struct tcp_opt *tp)
+{
+#if 0
+ tp->snd_cwnd = min(tp->snd_cwnd,
+ tcp_packets_in_flight(tp)+tcp_max_burst(tp));
+ tp->snd_cwnd_stamp = tcp_time_stamp;
+#endif
+}
+
+/* Decrease cwnd each second ack. */
+
+static void tcp_cwnd_down(struct tcp_opt *tp)
+{
+#if 0
+ int decr = tp->snd_cwnd_cnt + 1;
+
+ tp->snd_cwnd_cnt = decr&1;
+ decr >>= 1;
+
+ if (decr && tp->snd_cwnd > tp->snd_ssthresh/2)
+ tp->snd_cwnd -= decr;
+
+ tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)+1);
+ tp->snd_cwnd_stamp = tcp_time_stamp;
+#endif
+}
+
+/* Nothing was retransmitted or returned timestamp is less
+ * than timestamp of the first retransmission.
+ */
+static __inline__ int tcp_packet_delayed(struct tcp_opt *tp)
+{
+#if 0
+ return !tp->retrans_stamp ||
+ (tp->saw_tstamp && tp->rcv_tsecr &&
+ (__s32)(tp->rcv_tsecr - tp->retrans_stamp) < 0);
+#else
+ return 0;
+#endif
+}
+
+/* Undo procedures. */
+
+#if FASTRETRANS_DEBUG > 1
+static void DBGUNDO(struct sock *sk, struct tcp_opt *tp, const char *msg)
+{
+#if 0
+ printk(KERN_DEBUG "Undo %s %u.%u.%u.%u/%u c%u l%u ss%u/%u p%u\n",
+ msg,
+ NIPQUAD(sk->daddr), ntohs(sk->dport),
+ tp->snd_cwnd, tp->left_out,
+ tp->snd_ssthresh, tp->prior_ssthresh, tp->packets_out);
+#endif
+}
+#else
+#define DBGUNDO(x...) do { } while (0)
+#endif
+
+static void tcp_undo_cwr(struct tcp_opt *tp, int undo)
+{
+#if 0
+ if (tp->prior_ssthresh) {
+ tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh<<1);
+
+ if (undo && tp->prior_ssthresh > tp->snd_ssthresh) {
+ tp->snd_ssthresh = tp->prior_ssthresh;
+ TCP_ECN_withdraw_cwr(tp);
+ }
+ } else {
+ tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh);
+ }
+ tcp_moderate_cwnd(tp);
+ tp->snd_cwnd_stamp = tcp_time_stamp;
+#endif
+}
+
+static inline int tcp_may_undo(struct tcp_opt *tp)
+{
+#if 0
+ return tp->undo_marker &&
+ (!tp->undo_retrans || tcp_packet_delayed(tp));
+#else
+ return 0;
+#endif
+}
+
+/* People celebrate: "We love our President!" */
+static int tcp_try_undo_recovery(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+ if (tcp_may_undo(tp)) {
+ /* Happy end! We did not retransmit anything
+ * or our original transmission succeeded.
+ */
+ DBGUNDO(sk, tp, tp->ca_state == TCP_CA_Loss ? "loss" : "retrans");
+ tcp_undo_cwr(tp, 1);
+ if (tp->ca_state == TCP_CA_Loss)
+ NET_INC_STATS_BH(TCPLossUndo);
+ else
+ NET_INC_STATS_BH(TCPFullUndo);
+ tp->undo_marker = 0;
+ }
+ if (tp->snd_una == tp->high_seq && IsReno(tp)) {
+ /* Hold old state until something *above* high_seq
+ * is ACKed. For Reno it is MUST to prevent false
+ * fast retransmits (RFC2582). SACK TCP is safe. */
+ tcp_moderate_cwnd(tp);
+ return 1;
+ }
+ tp->ca_state = TCP_CA_Open;
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+/* Try to undo cwnd reduction, because D-SACKs acked all retransmitted data */
+static void tcp_try_undo_dsack(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+ if (tp->undo_marker && !tp->undo_retrans) {
+ DBGUNDO(sk, tp, "D-SACK");
+ tcp_undo_cwr(tp, 1);
+ tp->undo_marker = 0;
+ NET_INC_STATS_BH(TCPDSACKUndo);
+ }
+#endif
+}
+
+/* Undo during fast recovery after partial ACK. */
+
+static int tcp_try_undo_partial(struct sock *sk, struct tcp_opt *tp, int acked)
+{
+#if 0
+ /* Partial ACK arrived. Force Hoe's retransmit. */
+ int failed = IsReno(tp) || tp->fackets_out>tp->reordering;
+
+ if (tcp_may_undo(tp)) {
+ /* Plain luck! Hole if filled with delayed
+ * packet, rather than with a retransmit.
+ */
+ if (tp->retrans_out == 0)
+ tp->retrans_stamp = 0;
+
+ tcp_update_reordering(tp, tcp_fackets_out(tp)+acked, 1);
+
+ DBGUNDO(sk, tp, "Hoe");
+ tcp_undo_cwr(tp, 0);
+ NET_INC_STATS_BH(TCPPartialUndo);
+
+ /* So... Do not make Hoe's retransmit yet.
+ * If the first packet was delayed, the rest
+ * ones are most probably delayed as well.
+ */
+ failed = 0;
+ }
+ return failed;
+#else
+ return 0;
+#endif
+}
+
+/* Undo during loss recovery after partial ACK. */
+static int tcp_try_undo_loss(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+ if (tcp_may_undo(tp)) {
+ struct sk_buff *skb;
+ for_retrans_queue(skb, sk, tp) {
+ TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
+ }
+ DBGUNDO(sk, tp, "partial loss");
+ tp->lost_out = 0;
+ tp->left_out = tp->sacked_out;
+ tcp_undo_cwr(tp, 1);
+ NET_INC_STATS_BH(TCPLossUndo);
+ tp->retransmits = 0;
+ tp->undo_marker = 0;
+ if (!IsReno(tp))
+ tp->ca_state = TCP_CA_Open;
+ return 1;
+ }
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+static __inline__ void tcp_complete_cwr(struct tcp_opt *tp)
+{
+#if 0
+ tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
+ tp->snd_cwnd_stamp = tcp_time_stamp;
+#endif
+}
+
+static void tcp_try_to_open(struct sock *sk, struct tcp_opt *tp, int flag)
+{
+#if 0
+ tp->left_out = tp->sacked_out;
+
+ if (tp->retrans_out == 0)
+ tp->retrans_stamp = 0;
+
+ if (flag&FLAG_ECE)
+ tcp_enter_cwr(tp);
+
+ if (tp->ca_state != TCP_CA_CWR) {
+ int state = TCP_CA_Open;
+
+ if (tp->left_out ||
+ tp->retrans_out ||
+ tp->undo_marker)
+ state = TCP_CA_Disorder;
+
+ if (tp->ca_state != state) {
+ tp->ca_state = state;
+ tp->high_seq = tp->snd_nxt;
+ }
+ tcp_moderate_cwnd(tp);
+ } else {
+ tcp_cwnd_down(tp);
+ }
+#endif
+}
+
+/* Process an event, which can update packets-in-flight not trivially.
+ * Main goal of this function is to calculate new estimate for left_out,
+ * taking into account both packets sitting in receiver's buffer and
+ * packets lost by network.
+ *
+ * Besides that it does CWND reduction, when packet loss is detected
+ * and changes state of machine.
+ *
+ * It does _not_ decide what to send, it is made in function
+ * tcp_xmit_retransmit_queue().
+ */
+static void
+tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
+ int prior_packets, int flag)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int is_dupack = (tp->snd_una == prior_snd_una && !(flag&FLAG_NOT_DUP));
+
+ /* Some technical things:
+ * 1. Reno does not count dupacks (sacked_out) automatically. */
+ if (!tp->packets_out)
+ tp->sacked_out = 0;
+ /* 2. SACK counts snd_fack in packets inaccurately. */
+ if (tp->sacked_out == 0)
+ tp->fackets_out = 0;
+
+ /* Now state machine starts.
+ * A. ECE, hence prohibit cwnd undoing, the reduction is required. */
+ if (flag&FLAG_ECE)
+ tp->prior_ssthresh = 0;
+
+ /* B. In all the states check for reneging SACKs. */
+ if (tp->sacked_out && tcp_check_sack_reneging(sk, tp))
+ return;
+
+ /* C. Process data loss notification, provided it is valid. */
+ if ((flag&FLAG_DATA_LOST) &&
+ before(tp->snd_una, tp->high_seq) &&
+ tp->ca_state != TCP_CA_Open &&
+ tp->fackets_out > tp->reordering) {
+ tcp_mark_head_lost(sk, tp, tp->fackets_out-tp->reordering, tp->high_seq);
+ NET_INC_STATS_BH(TCPLoss);
+ }
+
+ /* D. Synchronize left_out to current state. */
+ tcp_sync_left_out(tp);
+
+ /* E. Check state exit conditions. State can be terminated
+ * when high_seq is ACKed. */
+ if (tp->ca_state == TCP_CA_Open) {
+ BUG_TRAP(tp->retrans_out == 0);
+ tp->retrans_stamp = 0;
+ } else if (!before(tp->snd_una, tp->high_seq)) {
+ switch (tp->ca_state) {
+ case TCP_CA_Loss:
+ tp->retransmits = 0;
+ if (tcp_try_undo_recovery(sk, tp))
+ return;
+ break;
+
+ case TCP_CA_CWR:
+ /* CWR is to be held something *above* high_seq
+ * is ACKed for CWR bit to reach receiver. */
+ if (tp->snd_una != tp->high_seq) {
+ tcp_complete_cwr(tp);
+ tp->ca_state = TCP_CA_Open;
+ }
+ break;
+
+ case TCP_CA_Disorder:
+ tcp_try_undo_dsack(sk, tp);
+ if (!tp->undo_marker ||
+ /* For SACK case do not Open to allow to undo
+ * catching for all duplicate ACKs. */
+ IsReno(tp) || tp->snd_una != tp->high_seq) {
+ tp->undo_marker = 0;
+ tp->ca_state = TCP_CA_Open;
+ }
+ break;
+
+ case TCP_CA_Recovery:
+ if (IsReno(tp))
+ tcp_reset_reno_sack(tp);
+ if (tcp_try_undo_recovery(sk, tp))
+ return;
+ tcp_complete_cwr(tp);
+ break;
+ }
+ }
+
+ /* F. Process state. */
+ switch (tp->ca_state) {
+ case TCP_CA_Recovery:
+ if (prior_snd_una == tp->snd_una) {
+ if (IsReno(tp) && is_dupack)
+ tcp_add_reno_sack(tp);
+ } else {
+ int acked = prior_packets - tp->packets_out;
+ if (IsReno(tp))
+ tcp_remove_reno_sacks(sk, tp, acked);
+ is_dupack = tcp_try_undo_partial(sk, tp, acked);
+ }
+ break;
+ case TCP_CA_Loss:
+ if (flag&FLAG_DATA_ACKED)
+ tp->retransmits = 0;
+ if (!tcp_try_undo_loss(sk, tp)) {
+ tcp_moderate_cwnd(tp);
+ tcp_xmit_retransmit_queue(sk);
+ return;
+ }
+ if (tp->ca_state != TCP_CA_Open)
+ return;
+ /* Loss is undone; fall through to processing in Open state. */
+ default:
+ if (IsReno(tp)) {
+ if (tp->snd_una != prior_snd_una)
+ tcp_reset_reno_sack(tp);
+ if (is_dupack)
+ tcp_add_reno_sack(tp);
+ }
+
+ if (tp->ca_state == TCP_CA_Disorder)
+ tcp_try_undo_dsack(sk, tp);
+
+ if (!tcp_time_to_recover(sk, tp)) {
+ tcp_try_to_open(sk, tp, flag);
+ return;
+ }
+
+ /* Otherwise enter Recovery state */
+
+ if (IsReno(tp))
+ NET_INC_STATS_BH(TCPRenoRecovery);
+ else
+ NET_INC_STATS_BH(TCPSackRecovery);
+
+ tp->high_seq = tp->snd_nxt;
+ tp->prior_ssthresh = 0;
+ tp->undo_marker = tp->snd_una;
+ tp->undo_retrans = tp->retrans_out;
+
+ if (tp->ca_state < TCP_CA_CWR) {
+ if (!(flag&FLAG_ECE))
+ tp->prior_ssthresh = tcp_current_ssthresh(tp);
+ tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
+ TCP_ECN_queue_cwr(tp);
+ }
+
+ tp->snd_cwnd_cnt = 0;
+ tp->ca_state = TCP_CA_Recovery;
+ }
+
+ if (is_dupack || tcp_head_timedout(sk, tp))
+ tcp_update_scoreboard(sk, tp);
+ tcp_cwnd_down(tp);
+ tcp_xmit_retransmit_queue(sk);
+#endif
+}
+
+/* Read draft-ietf-tcplw-high-performance before mucking
+ * with this code. (Superceeds RFC1323)
+ */
+static void tcp_ack_saw_tstamp(struct tcp_opt *tp, int flag)
+{
+#if 0
+ __u32 seq_rtt;
+
+ /* RTTM Rule: A TSecr value received in a segment is used to
+ * update the averaged RTT measurement only if the segment
+ * acknowledges some new data, i.e., only if it advances the
+ * left edge of the send window.
+ *
+ * See draft-ietf-tcplw-high-performance-00, section 3.3.
+ * 1998/04/10 Andrey V. Savochkin <saw@msu.ru>
+ *
+ * Changed: reset backoff as soon as we see the first valid sample.
+ * If we do not, we get strongly overstimated rto. With timestamps
+ * samples are accepted even from very old segments: f.e., when rtt=1
+ * increases to 8, we retransmit 5 times and after 8 seconds delayed
+ * answer arrives rto becomes 120 seconds! If at least one of segments
+ * in window is lost... Voila. --ANK (010210)
+ */
+ seq_rtt = tcp_time_stamp - tp->rcv_tsecr;
+ tcp_rtt_estimator(tp, seq_rtt);
+ tcp_set_rto(tp);
+ tp->backoff = 0;
+ tcp_bound_rto(tp);
+#endif
+}
+
+static void tcp_ack_no_tstamp(struct tcp_opt *tp, u32 seq_rtt, int flag)
+{
+#if 0
+ /* We don't have a timestamp. Can only use
+ * packets that are not retransmitted to determine
+ * rtt estimates. Also, we must not reset the
+ * backoff for rto until we get a non-retransmitted
+ * packet. This allows us to deal with a situation
+ * where the network delay has increased suddenly.
+ * I.e. Karn's algorithm. (SIGCOMM '87, p5.)
+ */
+
+ if (flag & FLAG_RETRANS_DATA_ACKED)
+ return;
+
+ tcp_rtt_estimator(tp, seq_rtt);
+ tcp_set_rto(tp);
+ tp->backoff = 0;
+ tcp_bound_rto(tp);
+#endif
+}
+
+static __inline__ void
+tcp_ack_update_rtt(struct tcp_opt *tp, int flag, s32 seq_rtt)
+{
+#if 0
+ /* Note that peer MAY send zero echo. In this case it is ignored. (rfc1323) */
+ if (tp->saw_tstamp && tp->rcv_tsecr)
+ tcp_ack_saw_tstamp(tp, flag);
+ else if (seq_rtt >= 0)
+ tcp_ack_no_tstamp(tp, seq_rtt, flag);
+#endif
+}
+
+/* This is Jacobson's slow start and congestion avoidance.
+ * SIGCOMM '88, p. 328.
+ */
+static __inline__ void tcp_cong_avoid(struct tcp_opt *tp)
+{
+#if 0
+ if (tp->snd_cwnd <= tp->snd_ssthresh) {
+ /* In "safe" area, increase. */
+ if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+ tp->snd_cwnd++;
+ } else {
+ /* In dangerous area, increase slowly.
+ * In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd
+ */
+ if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+ if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+ tp->snd_cwnd++;
+ tp->snd_cwnd_cnt=0;
+ } else
+ tp->snd_cwnd_cnt++;
+ }
+ tp->snd_cwnd_stamp = tcp_time_stamp;
+#endif
+}
+
+/* Restart timer after forward progress on connection.
+ * RFC2988 recommends to restart timer to now+rto.
+ */
+
+static __inline__ void tcp_ack_packets_out(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+ if (tp->packets_out==0) {
+ tcp_clear_xmit_timer(sk, TCP_TIME_RETRANS);
+ } else {
+ tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+ }
+#endif
+}
+
+/* Remove acknowledged frames from the retransmission queue. */
+static int tcp_clean_rtx_queue(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *skb;
+ __u32 now = tcp_time_stamp;
+ int acked = 0;
+ __s32 seq_rtt = -1;
+
+ while((skb=skb_peek(&sk->write_queue)) && (skb != tp->send_head)) {
+ struct tcp_skb_cb *scb = TCP_SKB_CB(skb);
+ __u8 sacked = scb->sacked;
+
+ /* If our packet is before the ack sequence we can
+ * discard it as it's confirmed to have arrived at
+ * the other end.
+ */
+ if (after(scb->end_seq, tp->snd_una))
+ break;
+
+ /* Initial outgoing SYN's get put onto the write_queue
+ * just like anything else we transmit. It is not
+ * true data, and if we misinform our callers that
+ * this ACK acks real data, we will erroneously exit
+ * connection startup slow start one packet too
+ * quickly. This is severely frowned upon behavior.
+ */
+ if(!(scb->flags & TCPCB_FLAG_SYN)) {
+ acked |= FLAG_DATA_ACKED;
+ } else {
+ acked |= FLAG_SYN_ACKED;
+ tp->retrans_stamp = 0;
+ }
+
+ if (sacked) {
+ if(sacked & TCPCB_RETRANS) {
+ if(sacked & TCPCB_SACKED_RETRANS)
+ tp->retrans_out--;
+ acked |= FLAG_RETRANS_DATA_ACKED;
+ seq_rtt = -1;
+ } else if (seq_rtt < 0)
+ seq_rtt = now - scb->when;
+ if(sacked & TCPCB_SACKED_ACKED)
+ tp->sacked_out--;
+ if(sacked & TCPCB_LOST)
+ tp->lost_out--;
+ if(sacked & TCPCB_URG) {
+ if (tp->urg_mode &&
+ !before(scb->end_seq, tp->snd_up))
+ tp->urg_mode = 0;
+ }
+ } else if (seq_rtt < 0)
+ seq_rtt = now - scb->when;
+ if(tp->fackets_out)
+ tp->fackets_out--;
+ tp->packets_out--;
+ __skb_unlink(skb, skb->list);
+ tcp_free_skb(sk, skb);
+ }
+
+ if (acked&FLAG_ACKED) {
+ tcp_ack_update_rtt(tp, acked, seq_rtt);
+ tcp_ack_packets_out(sk, tp);
+ }
+
+#if FASTRETRANS_DEBUG > 0
+ BUG_TRAP((int)tp->sacked_out >= 0);
+ BUG_TRAP((int)tp->lost_out >= 0);
+ BUG_TRAP((int)tp->retrans_out >= 0);
+ if (tp->packets_out==0 && tp->sack_ok) {
+ if (tp->lost_out) {
+ printk(KERN_DEBUG "Leak l=%u %d\n", tp->lost_out, tp->ca_state);
+ tp->lost_out = 0;
+ }
+ if (tp->sacked_out) {
+ printk(KERN_DEBUG "Leak s=%u %d\n", tp->sacked_out, tp->ca_state);
+ tp->sacked_out = 0;
+ }
+ if (tp->retrans_out) {
+ printk(KERN_DEBUG "Leak r=%u %d\n", tp->retrans_out, tp->ca_state);
+ tp->retrans_out = 0;
+ }
+ }
+#endif
+ return acked;
+#else
+ return 0;
+#endif
+}
+
+static void tcp_ack_probe(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ /* Was it a usable window open? */
+
+ if (!after(TCP_SKB_CB(tp->send_head)->end_seq, tp->snd_una + tp->snd_wnd)) {
+ tp->backoff = 0;
+ tcp_clear_xmit_timer(sk, TCP_TIME_PROBE0);
+ /* Socket must be waked up by subsequent tcp_data_snd_check().
+ * This function is not for random using!
+ */
+ } else {
+ tcp_reset_xmit_timer(sk, TCP_TIME_PROBE0,
+ min(tp->rto << tp->backoff, TCP_RTO_MAX));
+ }
+#endif
+}
+
+static __inline__ int tcp_ack_is_dubious(struct tcp_opt *tp, int flag)
+{
+#if 0
+ return (!(flag & FLAG_NOT_DUP) || (flag & FLAG_CA_ALERT) ||
+ tp->ca_state != TCP_CA_Open);
+#else
+ return 0;
+#endif
+}
+
+static __inline__ int tcp_may_raise_cwnd(struct tcp_opt *tp, int flag)
+{
+#if 0
+ return (!(flag & FLAG_ECE) || tp->snd_cwnd < tp->snd_ssthresh) &&
+ !((1<<tp->ca_state)&(TCPF_CA_Recovery|TCPF_CA_CWR));
+#else
+ return 0;
+#endif
+}
+
+/* Check that window update is acceptable.
+ * The function assumes that snd_una<=ack<=snd_next.
+ */
+static __inline__ int
+tcp_may_update_window(struct tcp_opt *tp, u32 ack, u32 ack_seq, u32 nwin)
+{
+#if 0
+ return (after(ack, tp->snd_una) ||
+ after(ack_seq, tp->snd_wl1) ||
+ (ack_seq == tp->snd_wl1 && nwin > tp->snd_wnd));
+#else
+ return 0;
+#endif
+}
+
+/* Update our send window.
+ *
+ * Window update algorithm, described in RFC793/RFC1122 (used in linux-2.2
+ * and in FreeBSD. NetBSD's one is even worse.) is wrong.
+ */
+static int tcp_ack_update_window(struct sock *sk, struct tcp_opt *tp,
+ struct sk_buff *skb, u32 ack, u32 ack_seq)
+{
+#if 0
+ int flag = 0;
+ u32 nwin = ntohs(skb->h.th->window) << tp->snd_wscale;
+
+ if (tcp_may_update_window(tp, ack, ack_seq, nwin)) {
+ flag |= FLAG_WIN_UPDATE;
+ tcp_update_wl(tp, ack, ack_seq);
+
+ if (tp->snd_wnd != nwin) {
+ tp->snd_wnd = nwin;
+
+ /* Note, it is the only place, where
+ * fast path is recovered for sending TCP.
+ */
+ tcp_fast_path_check(sk, tp);
+
+ if (nwin > tp->max_window) {
+ tp->max_window = nwin;
+ tcp_sync_mss(sk, tp->pmtu_cookie);
+ }
+ }
+ }
+
+ tp->snd_una = ack;
+
+ return flag;
+#else
+ return 0;
+#endif
+}
+
+/* This routine deals with incoming acks, but not outgoing ones. */
+static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ u32 prior_snd_una = tp->snd_una;
+ u32 ack_seq = TCP_SKB_CB(skb)->seq;
+ u32 ack = TCP_SKB_CB(skb)->ack_seq;
+ u32 prior_in_flight;
+ int prior_packets;
+
+ /* If the ack is newer than sent or older than previous acks
+ * then we can probably ignore it.
+ */
+ if (after(ack, tp->snd_nxt))
+ goto uninteresting_ack;
+
+ if (before(ack, prior_snd_una))
+ goto old_ack;
+
+ if (!(flag&FLAG_SLOWPATH) && after(ack, prior_snd_una)) {
+ /* Window is constant, pure forward advance.
+ * No more checks are required.
+ * Note, we use the fact that SND.UNA>=SND.WL2.
+ */
+ tcp_update_wl(tp, ack, ack_seq);
+ tp->snd_una = ack;
+ flag |= FLAG_WIN_UPDATE;
+
+ NET_INC_STATS_BH(TCPHPAcks);
+ } else {
+ if (ack_seq != TCP_SKB_CB(skb)->end_seq)
+ flag |= FLAG_DATA;
+ else
+ NET_INC_STATS_BH(TCPPureAcks);
+
+ flag |= tcp_ack_update_window(sk, tp, skb, ack, ack_seq);
+
+ if (TCP_SKB_CB(skb)->sacked)
+ flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una);
+
+ if (TCP_ECN_rcv_ecn_echo(tp, skb->h.th))
+ flag |= FLAG_ECE;
+ }
+
+ /* We passed data and got it acked, remove any soft error
+ * log. Something worked...
+ */
+ sk->err_soft = 0;
+ tp->rcv_tstamp = tcp_time_stamp;
+ if ((prior_packets = tp->packets_out) == 0)
+ goto no_queue;
+
+ prior_in_flight = tcp_packets_in_flight(tp);
+
+ /* See if we can take anything off of the retransmit queue. */
+ flag |= tcp_clean_rtx_queue(sk);
+
+ if (tcp_ack_is_dubious(tp, flag)) {
+ /* Advanve CWND, if state allows this. */
+ if ((flag&FLAG_DATA_ACKED) && prior_in_flight >= tp->snd_cwnd &&
+ tcp_may_raise_cwnd(tp, flag))
+ tcp_cong_avoid(tp);
+ tcp_fastretrans_alert(sk, prior_snd_una, prior_packets, flag);
+ } else {
+ if ((flag&FLAG_DATA_ACKED) && prior_in_flight >= tp->snd_cwnd)
+ tcp_cong_avoid(tp);
+ }
+
+ if ((flag & FLAG_FORWARD_PROGRESS) || !(flag&FLAG_NOT_DUP))
+ dst_confirm(sk->dst_cache);
+
+ return 1;
+
+no_queue:
+ tp->probes_out = 0;
+
+ /* If this ack opens up a zero window, clear backoff. It was
+ * being used to time the probes, and is probably far higher than
+ * it needs to be for normal retransmission.
+ */
+ if (tp->send_head)
+ tcp_ack_probe(sk);
+ return 1;
+
+old_ack:
+ if (TCP_SKB_CB(skb)->sacked)
+ tcp_sacktag_write_queue(sk, skb, prior_snd_una);
+
+uninteresting_ack:
+ SOCK_DEBUG(sk, "Ack %u out of %u:%u\n", ack, tp->snd_una, tp->snd_nxt);
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+
+/* Look for tcp options. Normally only called on SYN and SYNACK packets.
+ * But, this can also be called on packets in the established flow when
+ * the fast version below fails.
+ */
+void tcp_parse_options(struct sk_buff *skb, struct tcp_opt *tp, int estab)
+{
+#if 0
+ unsigned char *ptr;
+ struct tcphdr *th = skb->h.th;
+ int length=(th->doff*4)-sizeof(struct tcphdr);
+
+ ptr = (unsigned char *)(th + 1);
+ tp->saw_tstamp = 0;
+
+ while(length>0) {
+ int opcode=*ptr++;
+ int opsize;
+
+ switch (opcode) {
+ case TCPOPT_EOL:
+ return;
+ case TCPOPT_NOP: /* Ref: RFC 793 section 3.1 */
+ length--;
+ continue;
+ default:
+ opsize=*ptr++;
+ if (opsize < 2) /* "silly options" */
+ return;
+ if (opsize > length)
+ return; /* don't parse partial options */
+ switch(opcode) {
+ case TCPOPT_MSS:
+ if(opsize==TCPOLEN_MSS && th->syn && !estab) {
+ u16 in_mss = ntohs(*(__u16 *)ptr);
+ if (in_mss) {
+ if (tp->user_mss && tp->user_mss < in_mss)
+ in_mss = tp->user_mss;
+ tp->mss_clamp = in_mss;
+ }
+ }
+ break;
+ case TCPOPT_WINDOW:
+ if(opsize==TCPOLEN_WINDOW && th->syn && !estab)
+ if (sysctl_tcp_window_scaling) {
+ tp->wscale_ok = 1;
+ tp->snd_wscale = *(__u8 *)ptr;
+ if(tp->snd_wscale > 14) {
+ if(net_ratelimit())
+ printk("tcp_parse_options: Illegal window "
+ "scaling value %d >14 received.",
+ tp->snd_wscale);
+ tp->snd_wscale = 14;
+ }
+ }
+ break;
+ case TCPOPT_TIMESTAMP:
+ if(opsize==TCPOLEN_TIMESTAMP) {
+ if ((estab && tp->tstamp_ok) ||
+ (!estab && sysctl_tcp_timestamps)) {
+ tp->saw_tstamp = 1;
+ tp->rcv_tsval = ntohl(*(__u32 *)ptr);
+ tp->rcv_tsecr = ntohl(*(__u32 *)(ptr+4));
+ }
+ }
+ break;
+ case TCPOPT_SACK_PERM:
+ if(opsize==TCPOLEN_SACK_PERM && th->syn && !estab) {
+ if (sysctl_tcp_sack) {
+ tp->sack_ok = 1;
+ tcp_sack_reset(tp);
+ }
+ }
+ break;
+
+ case TCPOPT_SACK:
+ if((opsize >= (TCPOLEN_SACK_BASE + TCPOLEN_SACK_PERBLOCK)) &&
+ !((opsize - TCPOLEN_SACK_BASE) % TCPOLEN_SACK_PERBLOCK) &&
+ tp->sack_ok) {
+ TCP_SKB_CB(skb)->sacked = (ptr - 2) - (unsigned char *)th;
+ }
+ };
+ ptr+=opsize-2;
+ length-=opsize;
+ };
+ }
+#endif
+}
+
+/* Fast parse options. This hopes to only see timestamps.
+ * If it is wrong it falls back on tcp_parse_options().
+ */
+static __inline__ int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr *th, struct tcp_opt *tp)
+{
+#if 0
+ if (th->doff == sizeof(struct tcphdr)>>2) {
+ tp->saw_tstamp = 0;
+ return 0;
+ } else if (tp->tstamp_ok &&
+ th->doff == (sizeof(struct tcphdr)>>2)+(TCPOLEN_TSTAMP_ALIGNED>>2)) {
+ __u32 *ptr = (__u32 *)(th + 1);
+ if (*ptr == ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
+ | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) {
+ tp->saw_tstamp = 1;
+ ++ptr;
+ tp->rcv_tsval = ntohl(*ptr);
+ ++ptr;
+ tp->rcv_tsecr = ntohl(*ptr);
+ return 1;
+ }
+ }
+ tcp_parse_options(skb, tp, 1);
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+extern __inline__ void
+tcp_store_ts_recent(struct tcp_opt *tp)
+{
+#if 0
+ tp->ts_recent = tp->rcv_tsval;
+ tp->ts_recent_stamp = xtime.tv_sec;
+#endif
+}
+
+extern __inline__ void
+tcp_replace_ts_recent(struct tcp_opt *tp, u32 seq)
+{
+#if 0
+ if (tp->saw_tstamp && !after(seq, tp->rcv_wup)) {
+ /* PAWS bug workaround wrt. ACK frames, the PAWS discard
+ * extra check below makes sure this can only happen
+ * for pure ACK frames. -DaveM
+ *
+ * Not only, also it occurs for expired timestamps.
+ */
+
+ if((s32)(tp->rcv_tsval - tp->ts_recent) >= 0 ||
+ xtime.tv_sec >= tp->ts_recent_stamp + TCP_PAWS_24DAYS)
+ tcp_store_ts_recent(tp);
+ }
+#endif
+}
+
+/* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM
+ *
+ * It is not fatal. If this ACK does _not_ change critical state (seqs, window)
+ * it can pass through stack. So, the following predicate verifies that
+ * this segment is not used for anything but congestion avoidance or
+ * fast retransmit. Moreover, we even are able to eliminate most of such
+ * second order effects, if we apply some small "replay" window (~RTO)
+ * to timestamp space.
+ *
+ * All these measures still do not guarantee that we reject wrapped ACKs
+ * on networks with high bandwidth, when sequence space is recycled fastly,
+ * but it guarantees that such events will be very rare and do not affect
+ * connection seriously. This doesn't look nice, but alas, PAWS is really
+ * buggy extension.
+ *
+ * [ Later note. Even worse! It is buggy for segments _with_ data. RFC
+ * states that events when retransmit arrives after original data are rare.
+ * It is a blatant lie. VJ forgot about fast retransmit! 8)8) It is
+ * the biggest problem on large power networks even with minor reordering.
+ * OK, let's give it small replay window. If peer clock is even 1hz, it is safe
+ * up to bandwidth of 18Gigabit/sec. 8) ]
+ */
+
+static int tcp_disordered_ack(struct tcp_opt *tp, struct sk_buff *skb)
+{
+#if 0
+ struct tcphdr *th = skb->h.th;
+ u32 seq = TCP_SKB_CB(skb)->seq;
+ u32 ack = TCP_SKB_CB(skb)->ack_seq;
+
+ return (/* 1. Pure ACK with correct sequence number. */
+ (th->ack && seq == TCP_SKB_CB(skb)->end_seq && seq == tp->rcv_nxt) &&
+
+ /* 2. ... and duplicate ACK. */
+ ack == tp->snd_una &&
+
+ /* 3. ... and does not update window. */
+ !tcp_may_update_window(tp, ack, seq, ntohs(th->window)<<tp->snd_wscale) &&
+
+ /* 4. ... and sits in replay window. */
+ (s32)(tp->ts_recent - tp->rcv_tsval) <= (tp->rto*1024)/HZ);
+#endif
+}
+
+extern __inline__ int tcp_paws_discard(struct tcp_opt *tp, struct sk_buff *skb)
+{
+#if 0
+ return ((s32)(tp->ts_recent - tp->rcv_tsval) > TCP_PAWS_WINDOW &&
+ xtime.tv_sec < tp->ts_recent_stamp + TCP_PAWS_24DAYS &&
+ !tcp_disordered_ack(tp, skb));
+#else
+ return 0;
+#endif
+}
+
+/* Check segment sequence number for validity.
+ *
+ * Segment controls are considered valid, if the segment
+ * fits to the window after truncation to the window. Acceptability
+ * of data (and SYN, FIN, of course) is checked separately.
+ * See tcp_data_queue(), for example.
+ *
+ * Also, controls (RST is main one) are accepted using RCV.WUP instead
+ * of RCV.NXT. Peer still did not advance his SND.UNA when we
+ * delayed ACK, so that hisSND.UNA<=ourRCV.WUP.
+ * (borrowed from freebsd)
+ */
+
+static inline int tcp_sequence(struct tcp_opt *tp, u32 seq, u32 end_seq)
+{
+#if 0
+ return !before(end_seq, tp->rcv_wup) &&
+ !after(seq, tp->rcv_nxt + tcp_receive_window(tp));
+#else
+ return 0;
+#endif
+}
+
+/* When we get a reset we do this. */
+static void tcp_reset(struct sock *sk)
+{
+#if 0
+ /* We want the right error as BSD sees it (and indeed as we do). */
+ switch (sk->state) {
+ case TCP_SYN_SENT:
+ sk->err = ECONNREFUSED;
+ break;
+ case TCP_CLOSE_WAIT:
+ sk->err = EPIPE;
+ break;
+ case TCP_CLOSE:
+ return;
+ default:
+ sk->err = ECONNRESET;
+ }
+
+ if (!sk->dead)
+ sk->error_report(sk);
+
+ tcp_done(sk);
+#endif
+}
+
+/*
+ * Process the FIN bit. This now behaves as it is supposed to work
+ * and the FIN takes effect when it is validly part of sequence
+ * space. Not before when we get holes.
+ *
+ * If we are ESTABLISHED, a received fin moves us to CLOSE-WAIT
+ * (and thence onto LAST-ACK and finally, CLOSE, we never enter
+ * TIME-WAIT)
+ *
+ * If we are in FINWAIT-1, a received FIN indicates simultaneous
+ * close and we go into CLOSING (and later onto TIME-WAIT)
+ *
+ * If we are in FINWAIT-2, a received FIN moves us to TIME-WAIT.
+ */
+static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ tcp_schedule_ack(tp);
+
+ sk->shutdown |= RCV_SHUTDOWN;
+ sk->done = 1;
+
+ switch(sk->state) {
+ case TCP_SYN_RECV:
+ case TCP_ESTABLISHED:
+ /* Move to CLOSE_WAIT */
+ tcp_set_state(sk, TCP_CLOSE_WAIT);
+ tp->ack.pingpong = 1;
+ break;
+
+ case TCP_CLOSE_WAIT:
+ case TCP_CLOSING:
+ /* Received a retransmission of the FIN, do
+ * nothing.
+ */
+ break;
+ case TCP_LAST_ACK:
+ /* RFC793: Remain in the LAST-ACK state. */
+ break;
+
+ case TCP_FIN_WAIT1:
+ /* This case occurs when a simultaneous close
+ * happens, we must ack the received FIN and
+ * enter the CLOSING state.
+ */
+ tcp_send_ack(sk);
+ tcp_set_state(sk, TCP_CLOSING);
+ break;
+ case TCP_FIN_WAIT2:
+ /* Received a FIN -- send ACK and enter TIME_WAIT. */
+ tcp_send_ack(sk);
+ tcp_time_wait(sk, TCP_TIME_WAIT, 0);
+ break;
+ default:
+ /* Only TCP_LISTEN and TCP_CLOSE are left, in these
+ * cases we should never reach this piece of code.
+ */
+ printk("tcp_fin: Impossible, sk->state=%d\n", sk->state);
+ break;
+ };
+
+ /* It _is_ possible, that we have something out-of-order _after_ FIN.
+ * Probably, we should reset in this case. For now drop them.
+ */
+ __skb_queue_purge(&tp->out_of_order_queue);
+ if (tp->sack_ok)
+ tcp_sack_reset(tp);
+ tcp_mem_reclaim(sk);
+
+ if (!sk->dead) {
+ sk->state_change(sk);
+
+ /* Do not send POLL_HUP for half duplex close. */
+ if (sk->shutdown == SHUTDOWN_MASK || sk->state == TCP_CLOSE)
+ sk_wake_async(sk, 1, POLL_HUP);
+ else
+ sk_wake_async(sk, 1, POLL_IN);
+ }
+#endif
+}
+
+static __inline__ int
+tcp_sack_extend(struct tcp_sack_block *sp, u32 seq, u32 end_seq)
+{
+#if 0
+ if (!after(seq, sp->end_seq) && !after(sp->start_seq, end_seq)) {
+ if (before(seq, sp->start_seq))
+ sp->start_seq = seq;
+ if (after(end_seq, sp->end_seq))
+ sp->end_seq = end_seq;
+ return 1;
+ }
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+static __inline__ void tcp_dsack_set(struct tcp_opt *tp, u32 seq, u32 end_seq)
+{
+#if 0
+ if (tp->sack_ok && sysctl_tcp_dsack) {
+ if (before(seq, tp->rcv_nxt))
+ NET_INC_STATS_BH(TCPDSACKOldSent);
+ else
+ NET_INC_STATS_BH(TCPDSACKOfoSent);
+
+ tp->dsack = 1;
+ tp->duplicate_sack[0].start_seq = seq;
+ tp->duplicate_sack[0].end_seq = end_seq;
+ tp->eff_sacks = min(tp->num_sacks+1, 4-tp->tstamp_ok);
+ }
+#endif
+}
+
+static __inline__ void tcp_dsack_extend(struct tcp_opt *tp, u32 seq, u32 end_seq)
+{
+#if 0
+ if (!tp->dsack)
+ tcp_dsack_set(tp, seq, end_seq);
+ else
+ tcp_sack_extend(tp->duplicate_sack, seq, end_seq);
+#endif
+}
+
+static void tcp_send_dupack(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
+ before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
+ NET_INC_STATS_BH(DelayedACKLost);
+ tcp_enter_quickack_mode(tp);
+
+ if (tp->sack_ok && sysctl_tcp_dsack) {
+ u32 end_seq = TCP_SKB_CB(skb)->end_seq;
+
+ if (after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt))
+ end_seq = tp->rcv_nxt;
+ tcp_dsack_set(tp, TCP_SKB_CB(skb)->seq, end_seq);
+ }
+ }
+
+ tcp_send_ack(sk);
+#endif
+}
+
+/* These routines update the SACK block as out-of-order packets arrive or
+ * in-order packets close up the sequence space.
+ */
+static void tcp_sack_maybe_coalesce(struct tcp_opt *tp)
+{
+#if 0
+ int this_sack;
+ struct tcp_sack_block *sp = &tp->selective_acks[0];
+ struct tcp_sack_block *swalk = sp+1;
+
+ /* See if the recent change to the first SACK eats into
+ * or hits the sequence space of other SACK blocks, if so coalesce.
+ */
+ for (this_sack = 1; this_sack < tp->num_sacks; ) {
+ if (tcp_sack_extend(sp, swalk->start_seq, swalk->end_seq)) {
+ int i;
+
+ /* Zap SWALK, by moving every further SACK up by one slot.
+ * Decrease num_sacks.
+ */
+ tp->num_sacks--;
+ tp->eff_sacks = min(tp->num_sacks+tp->dsack, 4-tp->tstamp_ok);
+ for(i=this_sack; i < tp->num_sacks; i++)
+ sp[i] = sp[i+1];
+ continue;
+ }
+ this_sack++, swalk++;
+ }
+#endif
+}
+
+static __inline__ void tcp_sack_swap(struct tcp_sack_block *sack1, struct tcp_sack_block *sack2)
+{
+#if 0
+ __u32 tmp;
+
+ tmp = sack1->start_seq;
+ sack1->start_seq = sack2->start_seq;
+ sack2->start_seq = tmp;
+
+ tmp = sack1->end_seq;
+ sack1->end_seq = sack2->end_seq;
+ sack2->end_seq = tmp;
+#endif
+}
+
+static void tcp_sack_new_ofo_skb(struct sock *sk, u32 seq, u32 end_seq)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct tcp_sack_block *sp = &tp->selective_acks[0];
+ int cur_sacks = tp->num_sacks;
+ int this_sack;
+
+ if (!cur_sacks)
+ goto new_sack;
+
+ for (this_sack=0; this_sack<cur_sacks; this_sack++, sp++) {
+ if (tcp_sack_extend(sp, seq, end_seq)) {
+ /* Rotate this_sack to the first one. */
+ for (; this_sack>0; this_sack--, sp--)
+ tcp_sack_swap(sp, sp-1);
+ if (cur_sacks > 1)
+ tcp_sack_maybe_coalesce(tp);
+ return;
+ }
+ }
+
+ /* Could not find an adjacent existing SACK, build a new one,
+ * put it at the front, and shift everyone else down. We
+ * always know there is at least one SACK present already here.
+ *
+ * If the sack array is full, forget about the last one.
+ */
+ if (this_sack >= 4) {
+ this_sack--;
+ tp->num_sacks--;
+ sp--;
+ }
+ for(; this_sack > 0; this_sack--, sp--)
+ *sp = *(sp-1);
+
+new_sack:
+ /* Build the new head SACK, and we're done. */
+ sp->start_seq = seq;
+ sp->end_seq = end_seq;
+ tp->num_sacks++;
+ tp->eff_sacks = min(tp->num_sacks+tp->dsack, 4-tp->tstamp_ok);
+#endif
+}
+
+/* RCV.NXT advances, some SACKs should be eaten. */
+
+static void tcp_sack_remove(struct tcp_opt *tp)
+{
+#if 0
+ struct tcp_sack_block *sp = &tp->selective_acks[0];
+ int num_sacks = tp->num_sacks;
+ int this_sack;
+
+ /* Empty ofo queue, hence, all the SACKs are eaten. Clear. */
+ if (skb_queue_len(&tp->out_of_order_queue) == 0) {
+ tp->num_sacks = 0;
+ tp->eff_sacks = tp->dsack;
+ return;
+ }
+
+ for(this_sack = 0; this_sack < num_sacks; ) {
+ /* Check if the start of the sack is covered by RCV.NXT. */
+ if (!before(tp->rcv_nxt, sp->start_seq)) {
+ int i;
+
+ /* RCV.NXT must cover all the block! */
+ BUG_TRAP(!before(tp->rcv_nxt, sp->end_seq));
+
+ /* Zap this SACK, by moving forward any other SACKS. */
+ for (i=this_sack+1; i < num_sacks; i++)
+ tp->selective_acks[i-1] = tp->selective_acks[i];
+ num_sacks--;
+ continue;
+ }
+ this_sack++;
+ sp++;
+ }
+ if (num_sacks != tp->num_sacks) {
+ tp->num_sacks = num_sacks;
+ tp->eff_sacks = min(tp->num_sacks+tp->dsack, 4-tp->tstamp_ok);
+ }
+#endif
+}
+
+/* This one checks to see if we can put data from the
+ * out_of_order queue into the receive_queue.
+ */
+static void tcp_ofo_queue(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ __u32 dsack_high = tp->rcv_nxt;
+ struct sk_buff *skb;
+
+ while ((skb = skb_peek(&tp->out_of_order_queue)) != NULL) {
+ if (after(TCP_SKB_CB(skb)->seq, tp->rcv_nxt))
+ break;
+
+ if (before(TCP_SKB_CB(skb)->seq, dsack_high)) {
+ __u32 dsack = dsack_high;
+ if (before(TCP_SKB_CB(skb)->end_seq, dsack_high))
+ dsack_high = TCP_SKB_CB(skb)->end_seq;
+ tcp_dsack_extend(tp, TCP_SKB_CB(skb)->seq, dsack);
+ }
+
+ if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) {
+ SOCK_DEBUG(sk, "ofo packet was already received \n");
+ __skb_unlink(skb, skb->list);
+ __kfree_skb(skb);
+ continue;
+ }
+ SOCK_DEBUG(sk, "ofo requeuing : rcv_next %X seq %X - %X\n",
+ tp->rcv_nxt, TCP_SKB_CB(skb)->seq,
+ TCP_SKB_CB(skb)->end_seq);
+
+ __skb_unlink(skb, skb->list);
+ __skb_queue_tail(&sk->receive_queue, skb);
+ tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+ if(skb->h.th->fin)
+ tcp_fin(skb, sk, skb->h.th);
+ }
+#endif
+}
+
+static inline int tcp_rmem_schedule(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+ return (int)skb->truesize <= sk->forward_alloc ||
+ tcp_mem_schedule(sk, skb->truesize, 1);
+#else
+ return 0;
+#endif
+}
+
+static int tcp_prune_queue(struct sock *sk);
+
+static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+ struct tcphdr *th = skb->h.th;
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int eaten = -1;
+
+ if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq)
+ goto drop;
+
+ th = skb->h.th;
+ __skb_pull(skb, th->doff*4);
+
+ TCP_ECN_accept_cwr(tp, skb);
+
+ if (tp->dsack) {
+ tp->dsack = 0;
+ tp->eff_sacks = min_t(unsigned int, tp->num_sacks, 4-tp->tstamp_ok);
+ }
+
+ /* Queue data for delivery to the user.
+ * Packets in sequence go to the receive queue.
+ * Out of sequence packets to the out_of_order_queue.
+ */
+ if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt) {
+ if (tcp_receive_window(tp) == 0)
+ goto out_of_window;
+
+ /* Ok. In sequence. In window. */
+ if (tp->ucopy.task == current &&
+ tp->copied_seq == tp->rcv_nxt &&
+ tp->ucopy.len &&
+ sk->lock.users &&
+ !tp->urg_data) {
+ int chunk = min_t(unsigned int, skb->len, tp->ucopy.len);
+
+ __set_current_state(TASK_RUNNING);
+
+ local_bh_enable();
+ if (!skb_copy_datagram_iovec(skb, 0, tp->ucopy.iov, chunk)) {
+ tp->ucopy.len -= chunk;
+ tp->copied_seq += chunk;
+ eaten = (chunk == skb->len && !th->fin);
+ }
+ local_bh_disable();
+ }
+
+ if (eaten <= 0) {
+queue_and_out:
+ if (eaten < 0 &&
+ (atomic_read(&sk->rmem_alloc) > sk->rcvbuf ||
+ !tcp_rmem_schedule(sk, skb))) {
+ if (tcp_prune_queue(sk) < 0 || !tcp_rmem_schedule(sk, skb))
+ goto drop;
+ }
+ tcp_set_owner_r(skb, sk);
+ __skb_queue_tail(&sk->receive_queue, skb);
+ }
+ tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+ if(skb->len)
+ tcp_event_data_recv(sk, tp, skb);
+ if(th->fin)
+ tcp_fin(skb, sk, th);
+
+ if (skb_queue_len(&tp->out_of_order_queue)) {
+ tcp_ofo_queue(sk);
+
+ /* RFC2581. 4.2. SHOULD send immediate ACK, when
+ * gap in queue is filled.
+ */
+ if (skb_queue_len(&tp->out_of_order_queue) == 0)
+ tp->ack.pingpong = 0;
+ }
+
+ if(tp->num_sacks)
+ tcp_sack_remove(tp);
+
+ tcp_fast_path_check(sk, tp);
+
+ if (eaten > 0) {
+ __kfree_skb(skb);
+ } else if (!sk->dead)
+ sk->data_ready(sk, 0);
+ return;
+ }
+
+ if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) {
+ /* A retransmit, 2nd most common case. Force an immediate ack. */
+ NET_INC_STATS_BH(DelayedACKLost);
+ tcp_dsack_set(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq);
+
+out_of_window:
+ tcp_enter_quickack_mode(tp);
+ tcp_schedule_ack(tp);
+drop:
+ __kfree_skb(skb);
+ return;
+ }
+
+ /* Out of window. F.e. zero window probe. */
+ if (!before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt+tcp_receive_window(tp)))
+ goto out_of_window;
+
+ tcp_enter_quickack_mode(tp);
+
+ if (before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
+ /* Partial packet, seq < rcv_next < end_seq */
+ SOCK_DEBUG(sk, "partial packet: rcv_next %X seq %X - %X\n",
+ tp->rcv_nxt, TCP_SKB_CB(skb)->seq,
+ TCP_SKB_CB(skb)->end_seq);
+
+ tcp_dsack_set(tp, TCP_SKB_CB(skb)->seq, tp->rcv_nxt);
+
+ /* If window is closed, drop tail of packet. But after
+ * remembering D-SACK for its head made in previous line.
+ */
+ if (!tcp_receive_window(tp))
+ goto out_of_window;
+ goto queue_and_out;
+ }
+
+ TCP_ECN_check_ce(tp, skb);
+
+ if (atomic_read(&sk->rmem_alloc) > sk->rcvbuf ||
+ !tcp_rmem_schedule(sk, skb)) {
+ if (tcp_prune_queue(sk) < 0 || !tcp_rmem_schedule(sk, skb))
+ goto drop;
+ }
+
+ /* Disable header prediction. */
+ tp->pred_flags = 0;
+ tcp_schedule_ack(tp);
+
+ SOCK_DEBUG(sk, "out of order segment: rcv_next %X seq %X - %X\n",
+ tp->rcv_nxt, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq);
+
+ tcp_set_owner_r(skb, sk);
+
+ if (skb_peek(&tp->out_of_order_queue) == NULL) {
+ /* Initial out of order segment, build 1 SACK. */
+ if(tp->sack_ok) {
+ tp->num_sacks = 1;
+ tp->dsack = 0;
+ tp->eff_sacks = 1;
+ tp->selective_acks[0].start_seq = TCP_SKB_CB(skb)->seq;
+ tp->selective_acks[0].end_seq = TCP_SKB_CB(skb)->end_seq;
+ }
+ __skb_queue_head(&tp->out_of_order_queue,skb);
+ } else {
+ struct sk_buff *skb1=tp->out_of_order_queue.prev;
+ u32 seq = TCP_SKB_CB(skb)->seq;
+ u32 end_seq = TCP_SKB_CB(skb)->end_seq;
+
+ if (seq == TCP_SKB_CB(skb1)->end_seq) {
+ __skb_append(skb1, skb);
+
+ if (tp->num_sacks == 0 ||
+ tp->selective_acks[0].end_seq != seq)
+ goto add_sack;
+
+ /* Common case: data arrive in order after hole. */
+ tp->selective_acks[0].end_seq = end_seq;
+ return;
+ }
+
+ /* Find place to insert this segment. */
+ do {
+ if (!after(TCP_SKB_CB(skb1)->seq, seq))
+ break;
+ } while ((skb1=skb1->prev) != (struct sk_buff*)&tp->out_of_order_queue);
+
+ /* Do skb overlap to previous one? */
+ if (skb1 != (struct sk_buff*)&tp->out_of_order_queue &&
+ before(seq, TCP_SKB_CB(skb1)->end_seq)) {
+ if (!after(end_seq, TCP_SKB_CB(skb1)->end_seq)) {
+ /* All the bits are present. Drop. */
+ __kfree_skb(skb);
+ tcp_dsack_set(tp, seq, end_seq);
+ goto add_sack;
+ }
+ if (after(seq, TCP_SKB_CB(skb1)->seq)) {
+ /* Partial overlap. */
+ tcp_dsack_set(tp, seq, TCP_SKB_CB(skb1)->end_seq);
+ } else {
+ skb1 = skb1->prev;
+ }
+ }
+ __skb_insert(skb, skb1, skb1->next, &tp->out_of_order_queue);
+
+ /* And clean segments covered by new one as whole. */
+ while ((skb1 = skb->next) != (struct sk_buff*)&tp->out_of_order_queue &&
+ after(end_seq, TCP_SKB_CB(skb1)->seq)) {
+ if (before(end_seq, TCP_SKB_CB(skb1)->end_seq)) {
+ tcp_dsack_extend(tp, TCP_SKB_CB(skb1)->seq, end_seq);
+ break;
+ }
+ __skb_unlink(skb1, skb1->list);
+ tcp_dsack_extend(tp, TCP_SKB_CB(skb1)->seq, TCP_SKB_CB(skb1)->end_seq);
+ __kfree_skb(skb1);
+ }
+
+add_sack:
+ if (tp->sack_ok)
+ tcp_sack_new_ofo_skb(sk, seq, end_seq);
+ }
+#endif
+}
+
+/* Collapse contiguous sequence of skbs head..tail with
+ * sequence numbers start..end.
+ * Segments with FIN/SYN are not collapsed (only because this
+ * simplifies code)
+ */
+static void
+tcp_collapse(struct sock *sk, struct sk_buff *head,
+ struct sk_buff *tail, u32 start, u32 end)
+{
+#if 0
+ struct sk_buff *skb;
+
+ /* First, check that queue is collapsable and find
+ * the point where collapsing can be useful. */
+ for (skb = head; skb != tail; ) {
+ /* No new bits? It is possible on ofo queue. */
+ if (!before(start, TCP_SKB_CB(skb)->end_seq)) {
+ struct sk_buff *next = skb->next;
+ __skb_unlink(skb, skb->list);
+ __kfree_skb(skb);
+ NET_INC_STATS_BH(TCPRcvCollapsed);
+ skb = next;
+ continue;
+ }
+
+ /* The first skb to collapse is:
+ * - not SYN/FIN and
+ * - bloated or contains data before "start" or
+ * overlaps to the next one.
+ */
+ if (!skb->h.th->syn && !skb->h.th->fin &&
+ (tcp_win_from_space(skb->truesize) > skb->len ||
+ before(TCP_SKB_CB(skb)->seq, start) ||
+ (skb->next != tail &&
+ TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb->next)->seq)))
+ break;
+
+ /* Decided to skip this, advance start seq. */
+ start = TCP_SKB_CB(skb)->end_seq;
+ skb = skb->next;
+ }
+ if (skb == tail || skb->h.th->syn || skb->h.th->fin)
+ return;
+
+ while (before(start, end)) {
+ struct sk_buff *nskb;
+ int header = skb_headroom(skb);
+ int copy = (PAGE_SIZE - sizeof(struct sk_buff) -
+ sizeof(struct skb_shared_info) - header - 31)&~15;
+
+ /* Too big header? This can happen with IPv6. */
+ if (copy < 0)
+ return;
+ if (end-start < copy)
+ copy = end-start;
+ nskb = alloc_skb(copy+header, GFP_ATOMIC);
+ if (!nskb)
+ return;
+ skb_reserve(nskb, header);
+ memcpy(nskb->head, skb->head, header);
+ nskb->nh.raw = nskb->head + (skb->nh.raw-skb->head);
+ nskb->h.raw = nskb->head + (skb->h.raw-skb->head);
+ nskb->mac.raw = nskb->head + (skb->mac.raw-skb->head);
+ memcpy(nskb->cb, skb->cb, sizeof(skb->cb));
+ TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(nskb)->end_seq = start;
+ __skb_insert(nskb, skb->prev, skb, skb->list);
+ tcp_set_owner_r(nskb, sk);
+
+ /* Copy data, releasing collapsed skbs. */
+ while (copy > 0) {
+ int offset = start - TCP_SKB_CB(skb)->seq;
+ int size = TCP_SKB_CB(skb)->end_seq - start;
+
+ if (offset < 0) BUG();
+ if (size > 0) {
+ size = min(copy, size);
+ if (skb_copy_bits(skb, offset, skb_put(nskb, size), size))
+ BUG();
+ TCP_SKB_CB(nskb)->end_seq += size;
+ copy -= size;
+ start += size;
+ }
+ if (!before(start, TCP_SKB_CB(skb)->end_seq)) {
+ struct sk_buff *next = skb->next;
+ __skb_unlink(skb, skb->list);
+ __kfree_skb(skb);
+ NET_INC_STATS_BH(TCPRcvCollapsed);
+ skb = next;
+ if (skb == tail || skb->h.th->syn || skb->h.th->fin)
+ return;
+ }
+ }
+ }
+#endif
+}
+
+/* Collapse ofo queue. Algorithm: select contiguous sequence of skbs
+ * and tcp_collapse() them until all the queue is collapsed.
+ */
+static void tcp_collapse_ofo_queue(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *skb = skb_peek(&tp->out_of_order_queue);
+ struct sk_buff *head;
+ u32 start, end;
+
+ if (skb == NULL)
+ return;
+
+ start = TCP_SKB_CB(skb)->seq;
+ end = TCP_SKB_CB(skb)->end_seq;
+ head = skb;
+
+ for (;;) {
+ skb = skb->next;
+
+ /* Segment is terminated when we see gap or when
+ * we are at the end of all the queue. */
+ if (skb == (struct sk_buff *)&tp->out_of_order_queue ||
+ after(TCP_SKB_CB(skb)->seq, end) ||
+ before(TCP_SKB_CB(skb)->end_seq, start)) {
+ tcp_collapse(sk, head, skb, start, end);
+ head = skb;
+ if (skb == (struct sk_buff *)&tp->out_of_order_queue)
+ break;
+ /* Start new segment */
+ start = TCP_SKB_CB(skb)->seq;
+ end = TCP_SKB_CB(skb)->end_seq;
+ } else {
+ if (before(TCP_SKB_CB(skb)->seq, start))
+ start = TCP_SKB_CB(skb)->seq;
+ if (after(TCP_SKB_CB(skb)->end_seq, end))
+ end = TCP_SKB_CB(skb)->end_seq;
+ }
+ }
+#endif
+}
+
+/* Reduce allocated memory if we can, trying to get
+ * the socket within its memory limits again.
+ *
+ * Return less than zero if we should start dropping frames
+ * until the socket owning process reads some of the data
+ * to stabilize the situation.
+ */
+static int tcp_prune_queue(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ SOCK_DEBUG(sk, "prune_queue: c=%x\n", tp->copied_seq);
+
+ NET_INC_STATS_BH(PruneCalled);
+
+ if (atomic_read(&sk->rmem_alloc) >= sk->rcvbuf)
+ tcp_clamp_window(sk, tp);
+ else if (tcp_memory_pressure)
+ tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U*tp->advmss);
+
+ tcp_collapse_ofo_queue(sk);
+ tcp_collapse(sk, sk->receive_queue.next,
+ (struct sk_buff*)&sk->receive_queue,
+ tp->copied_seq, tp->rcv_nxt);
+ tcp_mem_reclaim(sk);
+
+ if (atomic_read(&sk->rmem_alloc) <= sk->rcvbuf)
+ return 0;
+
+ /* Collapsing did not help, destructive actions follow.
+ * This must not ever occur. */
+
+ /* First, purge the out_of_order queue. */
+ if (skb_queue_len(&tp->out_of_order_queue)) {
+ net_statistics[smp_processor_id()*2].OfoPruned += skb_queue_len(&tp->out_of_order_queue);
+ __skb_queue_purge(&tp->out_of_order_queue);
+
+ /* Reset SACK state. A conforming SACK implementation will
+ * do the same at a timeout based retransmit. When a connection
+ * is in a sad state like this, we care only about integrity
+ * of the connection not performance.
+ */
+ if(tp->sack_ok)
+ tcp_sack_reset(tp);
+ tcp_mem_reclaim(sk);
+ }
+
+ if(atomic_read(&sk->rmem_alloc) <= sk->rcvbuf)
+ return 0;
+
+ /* If we are really being abused, tell the caller to silently
+ * drop receive data on the floor. It will get retransmitted
+ * and hopefully then we'll have sufficient space.
+ */
+ NET_INC_STATS_BH(RcvPruned);
+
+ /* Massive buffer overcommit. */
+ tp->pred_flags = 0;
+ return -1;
+#else
+ return 0;
+#endif
+}
+
+
+/* RFC2861, slow part. Adjust cwnd, after it was not full during one rto.
+ * As additional protections, we do not touch cwnd in retransmission phases,
+ * and if application hit its sndbuf limit recently.
+ */
+void tcp_cwnd_application_limited(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ if (tp->ca_state == TCP_CA_Open &&
+ sk->socket && !test_bit(SOCK_NOSPACE, &sk->socket->flags)) {
+ /* Limited by application or receiver window. */
+ u32 win_used = max(tp->snd_cwnd_used, 2U);
+ if (win_used < tp->snd_cwnd) {
+ tp->snd_ssthresh = tcp_current_ssthresh(tp);
+ tp->snd_cwnd = (tp->snd_cwnd+win_used)>>1;
+ }
+ tp->snd_cwnd_used = 0;
+ }
+ tp->snd_cwnd_stamp = tcp_time_stamp;
+#endif
+}
+
+
+/* When incoming ACK allowed to free some skb from write_queue,
+ * we remember this event in flag tp->queue_shrunk and wake up socket
+ * on the exit from tcp input handler.
+ */
+static void tcp_new_space(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ if (tp->packets_out < tp->snd_cwnd &&
+ !(sk->userlocks&SOCK_SNDBUF_LOCK) &&
+ !tcp_memory_pressure &&
+ atomic_read(&tcp_memory_allocated) < sysctl_tcp_mem[0]) {
+ int sndmem, demanded;
+
+ sndmem = tp->mss_clamp+MAX_TCP_HEADER+16+sizeof(struct sk_buff);
+ demanded = max_t(unsigned int, tp->snd_cwnd, tp->reordering+1);
+ sndmem *= 2*demanded;
+ if (sndmem > sk->sndbuf)
+ sk->sndbuf = min(sndmem, sysctl_tcp_wmem[2]);
+ tp->snd_cwnd_stamp = tcp_time_stamp;
+ }
+
+ sk->write_space(sk);
+#endif
+}
+
+static inline void tcp_check_space(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ if (tp->queue_shrunk) {
+ tp->queue_shrunk = 0;
+ if (sk->socket && test_bit(SOCK_NOSPACE, &sk->socket->flags))
+ tcp_new_space(sk);
+ }
+#endif
+}
+
+static void __tcp_data_snd_check(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ if (after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd) ||
+ tcp_packets_in_flight(tp) >= tp->snd_cwnd ||
+ tcp_write_xmit(sk, tp->nonagle))
+ tcp_check_probe_timer(sk, tp);
+#endif
+}
+
+static __inline__ void tcp_data_snd_check(struct sock *sk)
+{
+#if 0
+ struct sk_buff *skb = sk->tp_pinfo.af_tcp.send_head;
+
+ if (skb != NULL)
+ __tcp_data_snd_check(sk, skb);
+ tcp_check_space(sk);
+#endif
+}
+
+/*
+ * Check if sending an ack is needed.
+ */
+static __inline__ void __tcp_ack_snd_check(struct sock *sk, int ofo_possible)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ /* More than one full frame received... */
+ if (((tp->rcv_nxt - tp->rcv_wup) > tp->ack.rcv_mss
+ /* ... and right edge of window advances far enough.
+ * (tcp_recvmsg() will send ACK otherwise). Or...
+ */
+ && __tcp_select_window(sk) >= tp->rcv_wnd) ||
+ /* We ACK each frame or... */
+ tcp_in_quickack_mode(tp) ||
+ /* We have out of order data. */
+ (ofo_possible &&
+ skb_peek(&tp->out_of_order_queue) != NULL)) {
+ /* Then ack it now */
+ tcp_send_ack(sk);
+ } else {
+ /* Else, send delayed ack. */
+ tcp_send_delayed_ack(sk);
+ }
+#endif
+}
+
+static __inline__ void tcp_ack_snd_check(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ if (!tcp_ack_scheduled(tp)) {
+ /* We sent a data segment already. */
+ return;
+ }
+ __tcp_ack_snd_check(sk, 1);
+#endif
+}
+
+/*
+ * This routine is only called when we have urgent data
+ * signalled. Its the 'slow' part of tcp_urg. It could be
+ * moved inline now as tcp_urg is only called from one
+ * place. We handle URGent data wrong. We have to - as
+ * BSD still doesn't use the correction from RFC961.
+ * For 1003.1g we should support a new option TCP_STDURG to permit
+ * either form (or just set the sysctl tcp_stdurg).
+ */
+
+static void tcp_check_urg(struct sock * sk, struct tcphdr * th)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ u32 ptr = ntohs(th->urg_ptr);
+
+ if (ptr && !sysctl_tcp_stdurg)
+ ptr--;
+ ptr += ntohl(th->seq);
+
+ /* Ignore urgent data that we've already seen and read. */
+ if (after(tp->copied_seq, ptr))
+ return;
+
+ /* Do not replay urg ptr.
+ *
+ * NOTE: interesting situation not covered by specs.
+ * Misbehaving sender may send urg ptr, pointing to segment,
+ * which we already have in ofo queue. We are not able to fetch
+ * such data and will stay in TCP_URG_NOTYET until will be eaten
+ * by recvmsg(). Seems, we are not obliged to handle such wicked
+ * situations. But it is worth to think about possibility of some
+ * DoSes using some hypothetical application level deadlock.
+ */
+ if (before(ptr, tp->rcv_nxt))
+ return;
+
+ /* Do we already have a newer (or duplicate) urgent pointer? */
+ if (tp->urg_data && !after(ptr, tp->urg_seq))
+ return;
+
+ /* Tell the world about our new urgent pointer. */
+ if (sk->proc != 0) {
+ if (sk->proc > 0)
+ kill_proc(sk->proc, SIGURG, 1);
+ else
+ kill_pg(-sk->proc, SIGURG, 1);
+ sk_wake_async(sk, 3, POLL_PRI);
+ }
+
+ /* We may be adding urgent data when the last byte read was
+ * urgent. To do this requires some care. We cannot just ignore
+ * tp->copied_seq since we would read the last urgent byte again
+ * as data, nor can we alter copied_seq until this data arrives
+ * or we break the sematics of SIOCATMARK (and thus sockatmark())
+ *
+ * NOTE. Double Dutch. Rendering to plain English: author of comment
+ * above did something sort of send("A", MSG_OOB); send("B", MSG_OOB);
+ * and expect that both A and B disappear from stream. This is _wrong_.
+ * Though this happens in BSD with high probability, this is occasional.
+ * Any application relying on this is buggy. Note also, that fix "works"
+ * only in this artificial test. Insert some normal data between A and B and we will
+ * decline of BSD again. Verdict: it is better to remove to trap
+ * buggy users.
+ */
+ if (tp->urg_seq == tp->copied_seq && tp->urg_data &&
+ !sk->urginline &&
+ tp->copied_seq != tp->rcv_nxt) {
+ struct sk_buff *skb = skb_peek(&sk->receive_queue);
+ tp->copied_seq++;
+ if (skb && !before(tp->copied_seq, TCP_SKB_CB(skb)->end_seq)) {
+ __skb_unlink(skb, skb->list);
+ __kfree_skb(skb);
+ }
+ }
+
+ tp->urg_data = TCP_URG_NOTYET;
+ tp->urg_seq = ptr;
+
+ /* Disable header prediction. */
+ tp->pred_flags = 0;
+#endif
+}
+
+/* This is the 'fast' part of urgent handling. */
+static inline void tcp_urg(struct sock *sk, struct sk_buff *skb, struct tcphdr *th)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ /* Check if we get a new urgent pointer - normally not. */
+ if (th->urg)
+ tcp_check_urg(sk,th);
+
+ /* Do we wait for any urgent data? - normally not... */
+ if (tp->urg_data == TCP_URG_NOTYET) {
+ u32 ptr = tp->urg_seq - ntohl(th->seq) + (th->doff*4) - th->syn;
+
+ /* Is the urgent pointer pointing into this packet? */
+ if (ptr < skb->len) {
+ u8 tmp;
+ if (skb_copy_bits(skb, ptr, &tmp, 1))
+ BUG();
+ tp->urg_data = TCP_URG_VALID | tmp;
+ if (!sk->dead)
+ sk->data_ready(sk,0);
+ }
+ }
+#endif
+}
+
+static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int chunk = skb->len - hlen;
+ int err;
+
+ local_bh_enable();
+ if (skb->ip_summed==CHECKSUM_UNNECESSARY)
+ err = skb_copy_datagram_iovec(skb, hlen, tp->ucopy.iov, chunk);
+ else
+ err = skb_copy_and_csum_datagram_iovec(skb, hlen, tp->ucopy.iov);
+
+ if (!err) {
+ tp->ucopy.len -= chunk;
+ tp->copied_seq += chunk;
+ }
+
+ local_bh_disable();
+ return err;
+#else
+ return 0;
+#endif
+}
+
+static int __tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+ int result;
+
+ if (sk->lock.users) {
+ local_bh_enable();
+ result = __tcp_checksum_complete(skb);
+ local_bh_disable();
+ } else {
+ result = __tcp_checksum_complete(skb);
+ }
+ return result;
+#else
+ return 0;
+#endif
+}
+
+static __inline__ int
+tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+ return skb->ip_summed != CHECKSUM_UNNECESSARY &&
+ __tcp_checksum_complete_user(sk, skb);
+#else
+ return 0;
+#endif
+}
+
+/*
+ * TCP receive function for the ESTABLISHED state.
+ *
+ * It is split into a fast path and a slow path. The fast path is
+ * disabled when:
+ * - A zero window was announced from us - zero window probing
+ * is only handled properly in the slow path.
+ * - Out of order segments arrived.
+ * - Urgent data is expected.
+ * - There is no buffer space left
+ * - Unexpected TCP flags/window values/header lengths are received
+ * (detected by checking the TCP header against pred_flags)
+ * - Data is sent in both directions. Fast path only supports pure senders
+ * or pure receivers (this means either the sequence number or the ack
+ * value must stay constant)
+ * - Unexpected TCP option.
+ *
+ * When these conditions are not satisfied it drops into a standard
+ * receive procedure patterned after RFC793 to handle all cases.
+ * The first three cases are guaranteed by proper pred_flags setting,
+ * the rest is checked inline. Fast processing is turned on in
+ * tcp_data_queue when everything is OK.
+ */
+int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
+ struct tcphdr *th, unsigned len)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ /*
+ * Header prediction.
+ * The code losely follows the one in the famous
+ * "30 instruction TCP receive" Van Jacobson mail.
+ *
+ * Van's trick is to deposit buffers into socket queue
+ * on a device interrupt, to call tcp_recv function
+ * on the receive process context and checksum and copy
+ * the buffer to user space. smart...
+ *
+ * Our current scheme is not silly either but we take the
+ * extra cost of the net_bh soft interrupt processing...
+ * We do checksum and copy also but from device to kernel.
+ */
+
+ tp->saw_tstamp = 0;
+
+ /* pred_flags is 0xS?10 << 16 + snd_wnd
+ * if header_predition is to be made
+ * 'S' will always be tp->tcp_header_len >> 2
+ * '?' will be 0 for the fast path, otherwise pred_flags is 0 to
+ * turn it off (when there are holes in the receive
+ * space for instance)
+ * PSH flag is ignored.
+ */
+
+ if ((tcp_flag_word(th) & TCP_HP_BITS) == tp->pred_flags &&
+ TCP_SKB_CB(skb)->seq == tp->rcv_nxt) {
+ int tcp_header_len = tp->tcp_header_len;
+
+ /* Timestamp header prediction: tcp_header_len
+ * is automatically equal to th->doff*4 due to pred_flags
+ * match.
+ */
+
+ /* Check timestamp */
+ if (tcp_header_len == sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED) {
+ __u32 *ptr = (__u32 *)(th + 1);
+
+ /* No? Slow path! */
+ if (*ptr != ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
+ | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP))
+ goto slow_path;
+
+ tp->saw_tstamp = 1;
+ ++ptr;
+ tp->rcv_tsval = ntohl(*ptr);
+ ++ptr;
+ tp->rcv_tsecr = ntohl(*ptr);
+
+ /* If PAWS failed, check it more carefully in slow path */
+ if ((s32)(tp->rcv_tsval - tp->ts_recent) < 0)
+ goto slow_path;
+
+ /* DO NOT update ts_recent here, if checksum fails
+ * and timestamp was corrupted part, it will result
+ * in a hung connection since we will drop all
+ * future packets due to the PAWS test.
+ */
+ }
+
+ if (len <= tcp_header_len) {
+ /* Bulk data transfer: sender */
+ if (len == tcp_header_len) {
+ /* Predicted packet is in window by definition.
+ * seq == rcv_nxt and rcv_wup <= rcv_nxt.
+ * Hence, check seq<=rcv_wup reduces to:
+ */
+ if (tcp_header_len ==
+ (sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED) &&
+ tp->rcv_nxt == tp->rcv_wup)
+ tcp_store_ts_recent(tp);
+ /* We know that such packets are checksummed
+ * on entry.
+ */
+ tcp_ack(sk, skb, 0);
+ __kfree_skb(skb);
+ tcp_data_snd_check(sk);
+ return 0;
+ } else { /* Header too small */
+ TCP_INC_STATS_BH(TcpInErrs);
+ goto discard;
+ }
+ } else {
+ int eaten = 0;
+
+ if (tp->ucopy.task == current &&
+ tp->copied_seq == tp->rcv_nxt &&
+ len - tcp_header_len <= tp->ucopy.len &&
+ sk->lock.users) {
+ __set_current_state(TASK_RUNNING);
+
+ if (!tcp_copy_to_iovec(sk, skb, tcp_header_len)) {
+ /* Predicted packet is in window by definition.
+ * seq == rcv_nxt and rcv_wup <= rcv_nxt.
+ * Hence, check seq<=rcv_wup reduces to:
+ */
+ if (tcp_header_len ==
+ (sizeof(struct tcphdr) +
+ TCPOLEN_TSTAMP_ALIGNED) &&
+ tp->rcv_nxt == tp->rcv_wup)
+ tcp_store_ts_recent(tp);
+
+ __skb_pull(skb, tcp_header_len);
+ tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+ NET_INC_STATS_BH(TCPHPHitsToUser);
+ eaten = 1;
+ }
+ }
+ if (!eaten) {
+ if (tcp_checksum_complete_user(sk, skb))
+ goto csum_error;
+
+ /* Predicted packet is in window by definition.
+ * seq == rcv_nxt and rcv_wup <= rcv_nxt.
+ * Hence, check seq<=rcv_wup reduces to:
+ */
+ if (tcp_header_len ==
+ (sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED) &&
+ tp->rcv_nxt == tp->rcv_wup)
+ tcp_store_ts_recent(tp);
+
+ if ((int)skb->truesize > sk->forward_alloc)
+ goto step5;
+
+ NET_INC_STATS_BH(TCPHPHits);
+
+ /* Bulk data transfer: receiver */
+ __skb_pull(skb,tcp_header_len);
+ __skb_queue_tail(&sk->receive_queue, skb);
+ tcp_set_owner_r(skb, sk);
+ tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+ }
+
+ tcp_event_data_recv(sk, tp, skb);
+
+ if (TCP_SKB_CB(skb)->ack_seq != tp->snd_una) {
+ /* Well, only one small jumplet in fast path... */
+ tcp_ack(sk, skb, FLAG_DATA);
+ tcp_data_snd_check(sk);
+ if (!tcp_ack_scheduled(tp))
+ goto no_ack;
+ }
+
+ if (eaten) {
+ if (tcp_in_quickack_mode(tp)) {
+ tcp_send_ack(sk);
+ } else {
+ tcp_send_delayed_ack(sk);
+ }
+ } else {
+ __tcp_ack_snd_check(sk, 0);
+ }
+
+no_ack:
+ if (eaten)
+ __kfree_skb(skb);
+ else
+ sk->data_ready(sk, 0);
+ return 0;
+ }
+ }
+
+slow_path:
+ if (len < (th->doff<<2) || tcp_checksum_complete_user(sk, skb))
+ goto csum_error;
+
+ /*
+ * RFC1323: H1. Apply PAWS check first.
+ */
+ if (tcp_fast_parse_options(skb, th, tp) && tp->saw_tstamp &&
+ tcp_paws_discard(tp, skb)) {
+ if (!th->rst) {
+ NET_INC_STATS_BH(PAWSEstabRejected);
+ tcp_send_dupack(sk, skb);
+ goto discard;
+ }
+ /* Resets are accepted even if PAWS failed.
+
+ ts_recent update must be made after we are sure
+ that the packet is in window.
+ */
+ }
+
+ /*
+ * Standard slow path.
+ */
+
+ if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) {
+ /* RFC793, page 37: "In all states except SYN-SENT, all reset
+ * (RST) segments are validated by checking their SEQ-fields."
+ * And page 69: "If an incoming segment is not acceptable,
+ * an acknowledgment should be sent in reply (unless the RST bit
+ * is set, if so drop the segment and return)".
+ */
+ if (!th->rst)
+ tcp_send_dupack(sk, skb);
+ goto discard;
+ }
+
+ if(th->rst) {
+ tcp_reset(sk);
+ goto discard;
+ }
+
+ tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
+
+ if (th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
+ TCP_INC_STATS_BH(TcpInErrs);
+ NET_INC_STATS_BH(TCPAbortOnSyn);
+ tcp_reset(sk);
+ return 1;
+ }
+
+step5:
+ if(th->ack)
+ tcp_ack(sk, skb, FLAG_SLOWPATH);
+
+ /* Process urgent data. */
+ tcp_urg(sk, skb, th);
+
+ /* step 7: process the segment text */
+ tcp_data_queue(sk, skb);
+
+ tcp_data_snd_check(sk);
+ tcp_ack_snd_check(sk);
+ return 0;
+
+csum_error:
+ TCP_INC_STATS_BH(TcpInErrs);
+
+discard:
+ __kfree_skb(skb);
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
+ struct tcphdr *th, unsigned len)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int saved_clamp = tp->mss_clamp;
+
+ tcp_parse_options(skb, tp, 0);
+
+ if (th->ack) {
+ /* rfc793:
+ * "If the state is SYN-SENT then
+ * first check the ACK bit
+ * If the ACK bit is set
+ * If SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send
+ * a reset (unless the RST bit is set, if so drop
+ * the segment and return)"
+ *
+ * We do not send data with SYN, so that RFC-correct
+ * test reduces to:
+ */
+ if (TCP_SKB_CB(skb)->ack_seq != tp->snd_nxt)
+ goto reset_and_undo;
+
+ if (tp->saw_tstamp && tp->rcv_tsecr &&
+ !between(tp->rcv_tsecr, tp->retrans_stamp, tcp_time_stamp)) {
+ NET_INC_STATS_BH(PAWSActiveRejected);
+ goto reset_and_undo;
+ }
+
+ /* Now ACK is acceptable.
+ *
+ * "If the RST bit is set
+ * If the ACK was acceptable then signal the user "error:
+ * connection reset", drop the segment, enter CLOSED state,
+ * delete TCB, and return."
+ */
+
+ if (th->rst) {
+ tcp_reset(sk);
+ goto discard;
+ }
+
+ /* rfc793:
+ * "fifth, if neither of the SYN or RST bits is set then
+ * drop the segment and return."
+ *
+ * See note below!
+ * --ANK(990513)
+ */
+ if (!th->syn)
+ goto discard_and_undo;
+
+ /* rfc793:
+ * "If the SYN bit is on ...
+ * are acceptable then ...
+ * (our SYN has been ACKed), change the connection
+ * state to ESTABLISHED..."
+ */
+
+ TCP_ECN_rcv_synack(tp, th);
+
+ tp->snd_wl1 = TCP_SKB_CB(skb)->seq;
+ tcp_ack(sk, skb, FLAG_SLOWPATH);
+
+ /* Ok.. it's good. Set up sequence numbers and
+ * move to established.
+ */
+ tp->rcv_nxt = TCP_SKB_CB(skb)->seq+1;
+ tp->rcv_wup = TCP_SKB_CB(skb)->seq+1;
+
+ /* RFC1323: The window in SYN & SYN/ACK segments is
+ * never scaled.
+ */
+ tp->snd_wnd = ntohs(th->window);
+ tcp_init_wl(tp, TCP_SKB_CB(skb)->ack_seq, TCP_SKB_CB(skb)->seq);
+
+ if (tp->wscale_ok == 0) {
+ tp->snd_wscale = tp->rcv_wscale = 0;
+ tp->window_clamp = min(tp->window_clamp, 65535U);
+ }
+
+ if (tp->saw_tstamp) {
+ tp->tstamp_ok = 1;
+ tp->tcp_header_len =
+ sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED;
+ tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
+ tcp_store_ts_recent(tp);
+ } else {
+ tp->tcp_header_len = sizeof(struct tcphdr);
+ }
+
+ if (tp->sack_ok && sysctl_tcp_fack)
+ tp->sack_ok |= 2;
+
+ tcp_sync_mss(sk, tp->pmtu_cookie);
+ tcp_initialize_rcv_mss(sk);
+ tcp_init_metrics(sk);
+ tcp_init_buffer_space(sk);
+
+ if (sk->keepopen)
+ tcp_reset_keepalive_timer(sk, keepalive_time_when(tp));
+
+ if (tp->snd_wscale == 0)
+ __tcp_fast_path_on(tp, tp->snd_wnd);
+ else
+ tp->pred_flags = 0;
+
+ /* Remember, tcp_poll() does not lock socket!
+ * Change state from SYN-SENT only after copied_seq
+ * is initialized. */
+ tp->copied_seq = tp->rcv_nxt;
+ mb();
+ tcp_set_state(sk, TCP_ESTABLISHED);
+
+ if(!sk->dead) {
+ sk->state_change(sk);
+ sk_wake_async(sk, 0, POLL_OUT);
+ }
+
+ if (tp->write_pending || tp->defer_accept || tp->ack.pingpong) {
+ /* Save one ACK. Data will be ready after
+ * several ticks, if write_pending is set.
+ *
+ * It may be deleted, but with this feature tcpdumps
+ * look so _wonderfully_ clever, that I was not able
+ * to stand against the temptation 8) --ANK
+ */
+ tcp_schedule_ack(tp);
+ tp->ack.lrcvtime = tcp_time_stamp;
+ tp->ack.ato = TCP_ATO_MIN;
+ tcp_incr_quickack(tp);
+ tcp_enter_quickack_mode(tp);
+ tcp_reset_xmit_timer(sk, TCP_TIME_DACK, TCP_DELACK_MAX);
+
+discard:
+ __kfree_skb(skb);
+ return 0;
+ } else {
+ tcp_send_ack(sk);
+ }
+ return -1;
+ }
+
+ /* No ACK in the segment */
+
+ if (th->rst) {
+ /* rfc793:
+ * "If the RST bit is set
+ *
+ * Otherwise (no ACK) drop the segment and return."
+ */
+
+ goto discard_and_undo;
+ }
+
+ /* PAWS check. */
+ if (tp->ts_recent_stamp && tp->saw_tstamp && tcp_paws_check(tp, 0))
+ goto discard_and_undo;
+
+ if (th->syn) {
+ /* We see SYN without ACK. It is attempt of
+ * simultaneous connect with crossed SYNs.
+ * Particularly, it can be connect to self.
+ */
+ tcp_set_state(sk, TCP_SYN_RECV);
+
+ if (tp->saw_tstamp) {
+ tp->tstamp_ok = 1;
+ tcp_store_ts_recent(tp);
+ tp->tcp_header_len =
+ sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED;
+ } else {
+ tp->tcp_header_len = sizeof(struct tcphdr);
+ }
+
+ tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1;
+ tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1;
+
+ /* RFC1323: The window in SYN & SYN/ACK segments is
+ * never scaled.
+ */
+ tp->snd_wnd = ntohs(th->window);
+ tp->snd_wl1 = TCP_SKB_CB(skb)->seq;
+ tp->max_window = tp->snd_wnd;
+
+ tcp_sync_mss(sk, tp->pmtu_cookie);
+ tcp_initialize_rcv_mss(sk);
+
+ TCP_ECN_rcv_syn(tp, th);
+
+ tcp_send_synack(sk);
+#if 0
+ /* Note, we could accept data and URG from this segment.
+ * There are no obstacles to make this.
+ *
+ * However, if we ignore data in ACKless segments sometimes,
+ * we have no reasons to accept it sometimes.
+ * Also, seems the code doing it in step6 of tcp_rcv_state_process
+ * is not flawless. So, discard packet for sanity.
+ * Uncomment this return to process the data.
+ */
+ return -1;
+#else
+ goto discard;
+#endif
+ }
+ /* "fifth, if neither of the SYN or RST bits is set then
+ * drop the segment and return."
+ */
+
+discard_and_undo:
+ tcp_clear_options(tp);
+ tp->mss_clamp = saved_clamp;
+ goto discard;
+
+reset_and_undo:
+ tcp_clear_options(tp);
+ tp->mss_clamp = saved_clamp;
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+
+/*
+ * This function implements the receiving procedure of RFC 793 for
+ * all states except ESTABLISHED and TIME_WAIT.
+ * It's called from both tcp_v4_rcv and tcp_v6_rcv and should be
+ * address independent.
+ */
+
+int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
+ struct tcphdr *th, unsigned len)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int queued = 0;
+
+ tp->saw_tstamp = 0;
+
+ switch (sk->state) {
+ case TCP_CLOSE:
+ goto discard;
+
+ case TCP_LISTEN:
+ if(th->ack)
+ return 1;
+
+ if(th->rst)
+ goto discard;
+
+ if(th->syn) {
+ if(tp->af_specific->conn_request(sk, skb) < 0)
+ return 1;
+
+ /* Now we have several options: In theory there is
+ * nothing else in the frame. KA9Q has an option to
+ * send data with the syn, BSD accepts data with the
+ * syn up to the [to be] advertised window and
+ * Solaris 2.1 gives you a protocol error. For now
+ * we just ignore it, that fits the spec precisely
+ * and avoids incompatibilities. It would be nice in
+ * future to drop through and process the data.
+ *
+ * Now that TTCP is starting to be used we ought to
+ * queue this data.
+ * But, this leaves one open to an easy denial of
+ * service attack, and SYN cookies can't defend
+ * against this problem. So, we drop the data
+ * in the interest of security over speed.
+ */
+ goto discard;
+ }
+ goto discard;
+
+ case TCP_SYN_SENT:
+ queued = tcp_rcv_synsent_state_process(sk, skb, th, len);
+ if (queued >= 0)
+ return queued;
+
+ /* Do step6 onward by hand. */
+ tcp_urg(sk, skb, th);
+ __kfree_skb(skb);
+ tcp_data_snd_check(sk);
+ return 0;
+ }
+
+ if (tcp_fast_parse_options(skb, th, tp) && tp->saw_tstamp &&
+ tcp_paws_discard(tp, skb)) {
+ if (!th->rst) {
+ NET_INC_STATS_BH(PAWSEstabRejected);
+ tcp_send_dupack(sk, skb);
+ goto discard;
+ }
+ /* Reset is accepted even if it did not pass PAWS. */
+ }
+
+ /* step 1: check sequence number */
+ if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) {
+ if (!th->rst)
+ tcp_send_dupack(sk, skb);
+ goto discard;
+ }
+
+ /* step 2: check RST bit */
+ if(th->rst) {
+ tcp_reset(sk);
+ goto discard;
+ }
+
+ tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
+
+ /* step 3: check security and precedence [ignored] */
+
+ /* step 4:
+ *
+ * Check for a SYN in window.
+ */
+ if (th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
+ NET_INC_STATS_BH(TCPAbortOnSyn);
+ tcp_reset(sk);
+ return 1;
+ }
+
+ /* step 5: check the ACK field */
+ if (th->ack) {
+ int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH);
+
+ switch(sk->state) {
+ case TCP_SYN_RECV:
+ if (acceptable) {
+ tp->copied_seq = tp->rcv_nxt;
+ mb();
+ tcp_set_state(sk, TCP_ESTABLISHED);
+ sk->state_change(sk);
+
+ /* Note, that this wakeup is only for marginal
+ * crossed SYN case. Passively open sockets
+ * are not waked up, because sk->sleep == NULL
+ * and sk->socket == NULL.
+ */
+ if (sk->socket) {
+ sk_wake_async(sk,0,POLL_OUT);
+ }
+
+ tp->snd_una = TCP_SKB_CB(skb)->ack_seq;
+ tp->snd_wnd = ntohs(th->window) << tp->snd_wscale;
+ tcp_init_wl(tp, TCP_SKB_CB(skb)->ack_seq, TCP_SKB_CB(skb)->seq);
+
+ /* tcp_ack considers this ACK as duplicate
+ * and does not calculate rtt.
+ * Fix it at least with timestamps.
+ */
+ if (tp->saw_tstamp && tp->rcv_tsecr && !tp->srtt)
+ tcp_ack_saw_tstamp(tp, 0);
+
+ if (tp->tstamp_ok)
+ tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
+
+ tcp_init_metrics(sk);
+ tcp_initialize_rcv_mss(sk);
+ tcp_init_buffer_space(sk);
+ tcp_fast_path_on(tp);
+ } else {
+ return 1;
+ }
+ break;
+
+ case TCP_FIN_WAIT1:
+ if (tp->snd_una == tp->write_seq) {
+ tcp_set_state(sk, TCP_FIN_WAIT2);
+ sk->shutdown |= SEND_SHUTDOWN;
+ dst_confirm(sk->dst_cache);
+
+ if (!sk->dead) {
+ /* Wake up lingering close() */
+ sk->state_change(sk);
+ } else {
+ int tmo;
+
+ if (tp->linger2 < 0 ||
+ (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
+ after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt))) {
+ tcp_done(sk);
+ NET_INC_STATS_BH(TCPAbortOnData);
+ return 1;
+ }
+
+ tmo = tcp_fin_time(tp);
+ if (tmo > TCP_TIMEWAIT_LEN) {
+ tcp_reset_keepalive_timer(sk, tmo - TCP_TIMEWAIT_LEN);
+ } else if (th->fin || sk->lock.users) {
+ /* Bad case. We could lose such FIN otherwise.
+ * It is not a big problem, but it looks confusing
+ * and not so rare event. We still can lose it now,
+ * if it spins in bh_lock_sock(), but it is really
+ * marginal case.
+ */
+ tcp_reset_keepalive_timer(sk, tmo);
+ } else {
+ tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
+ goto discard;
+ }
+ }
+ }
+ break;
+
+ case TCP_CLOSING:
+ if (tp->snd_una == tp->write_seq) {
+ tcp_time_wait(sk, TCP_TIME_WAIT, 0);
+ goto discard;
+ }
+ break;
+
+ case TCP_LAST_ACK:
+ if (tp->snd_una == tp->write_seq) {
+ tcp_update_metrics(sk);
+ tcp_done(sk);
+ goto discard;
+ }
+ break;
+ }
+ } else
+ goto discard;
+
+ /* step 6: check the URG bit */
+ tcp_urg(sk, skb, th);
+
+ /* step 7: process the segment text */
+ switch (sk->state) {
+ case TCP_CLOSE_WAIT:
+ case TCP_CLOSING:
+ case TCP_LAST_ACK:
+ if (!before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt))
+ break;
+ case TCP_FIN_WAIT1:
+ case TCP_FIN_WAIT2:
+ /* RFC 793 says to queue data in these states,
+ * RFC 1122 says we MUST send a reset.
+ * BSD 4.4 also does reset.
+ */
+ if (sk->shutdown & RCV_SHUTDOWN) {
+ if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
+ after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt)) {
+ NET_INC_STATS_BH(TCPAbortOnData);
+ tcp_reset(sk);
+ return 1;
+ }
+ }
+ /* Fall through */
+ case TCP_ESTABLISHED:
+ tcp_data_queue(sk, skb);
+ queued = 1;
+ break;
+ }
+
+ /* tcp_data could move socket to TIME-WAIT */
+ if (sk->state != TCP_CLOSE) {
+ tcp_data_snd_check(sk);
+ tcp_ack_snd_check(sk);
+ }
+
+ if (!queued) {
+discard:
+ __kfree_skb(skb);
+ }
+ return 0;
+#else
+ return 0;
+#endif
+}
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS TCP/IP protocol driver
+ * FILE: transport/tcp/tcp_ipv4.c
+ * PURPOSE: Transmission Control Protocol
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISIONS:
+ * CSH 15-01-2003 Imported from linux kernel 2.4.20
+ */
+
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Implementation of the Transmission Control Protocol(TCP).
+ *
+ * Version: $Id$
+ *
+ * IPv4 specific functions
+ *
+ *
+ * code split from:
+ * linux/ipv4/tcp.c
+ * linux/ipv4/tcp_input.c
+ * linux/ipv4/tcp_output.c
+ *
+ * See tcp.c for author information
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/*
+ * Changes:
+ * David S. Miller : New socket lookup architecture.
+ * This code is dedicated to John Dyson.
+ * David S. Miller : Change semantics of established hash,
+ * half is devoted to TIME_WAIT sockets
+ * and the rest go in the other half.
+ * Andi Kleen : Add support for syncookies and fixed
+ * some bugs: ip options weren't passed to
+ * the TCP layer, missed a check for an ACK bit.
+ * Andi Kleen : Implemented fast path mtu discovery.
+ * Fixed many serious bugs in the
+ * open_request handling and moved
+ * most of it into the af independent code.
+ * Added tail drop and some other bugfixes.
+ * Added new listen sematics.
+ * Mike McLagan : Routing by source
+ * Juan Jose Ciarlante: ip_dynaddr bits
+ * Andi Kleen: various fixes.
+ * Vitaly E. Lavrov : Transparent proxy revived after year coma.
+ * Andi Kleen : Fix new listen.
+ * Andi Kleen : Fix accept error reporting.
+ */
+
+#if 0
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/random.h>
+#include <linux/cache.h>
+#include <linux/init.h>
+
+#include <net/icmp.h>
+#include <net/tcp.h>
+#include <net/ipv6.h>
+#include <net/inet_common.h>
+
+#include <linux/inet.h>
+#include <linux/stddef.h>
+#include <linux/ipsec.h>
+#else
+#include "linux.h"
+#include "tcpcore.h"
+#endif
+
+extern int sysctl_ip_dynaddr;
+extern int sysctl_ip_default_ttl;
+int sysctl_tcp_tw_reuse = 0;
+
+/* Check TCP sequence numbers in ICMP packets. */
+#define ICMP_MIN_LENGTH 8
+
+/* Socket used for sending RSTs */
+#if 0
+static struct inode tcp_inode;
+static struct socket *tcp_socket=&tcp_inode.u.socket_i;
+#endif
+
+void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len,
+ struct sk_buff *skb);
+
+/*
+ * ALL members must be initialised to prevent gcc-2.7.2.3 miscompilation
+ */
+#if 0
+struct tcp_hashinfo __cacheline_aligned tcp_hashinfo = {
+ __tcp_ehash: NULL,
+ __tcp_bhash: NULL,
+ __tcp_bhash_size: 0,
+ __tcp_ehash_size: 0,
+ __tcp_listening_hash: { NULL, },
+ __tcp_lhash_lock: RW_LOCK_UNLOCKED,
+ __tcp_lhash_users: ATOMIC_INIT(0),
+ __tcp_lhash_wait:
+ __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.__tcp_lhash_wait),
+ __tcp_portalloc_lock: SPIN_LOCK_UNLOCKED
+};
+#endif
+
+/*
+ * This array holds the first and last local port number.
+ * For high-usage systems, use sysctl to change this to
+ * 32768-61000
+ */
+int sysctl_local_port_range[2] = { 1024, 4999 };
+int tcp_port_rover = (1024 - 1);
+
+static __inline__ int tcp_hashfn(__u32 laddr, __u16 lport,
+ __u32 faddr, __u16 fport)
+{
+ int h = ((laddr ^ lport) ^ (faddr ^ fport));
+ h ^= h>>16;
+ h ^= h>>8;
+ return h & (tcp_ehash_size - 1);
+}
+
+static __inline__ int tcp_sk_hashfn(struct sock *sk)
+{
+ __u32 laddr = sk->rcv_saddr;
+ __u16 lport = sk->num;
+ __u32 faddr = sk->daddr;
+ __u16 fport = sk->dport;
+
+ return tcp_hashfn(laddr, lport, faddr, fport);
+}
+
+/* Allocate and initialize a new TCP local port bind bucket.
+ * The bindhash mutex for snum's hash chain must be held here.
+ */
+struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *head,
+ unsigned short snum)
+{
+#if 0
+ struct tcp_bind_bucket *tb;
+
+ tb = kmem_cache_alloc(tcp_bucket_cachep, SLAB_ATOMIC);
+ if(tb != NULL) {
+ tb->port = snum;
+ tb->fastreuse = 0;
+ tb->owners = NULL;
+ if((tb->next = head->chain) != NULL)
+ tb->next->pprev = &tb->next;
+ head->chain = tb;
+ tb->pprev = &head->chain;
+ }
+ return tb;
+#else
+ return NULL;
+#endif
+}
+
+/* Caller must disable local BH processing. */
+static __inline__ void __tcp_inherit_port(struct sock *sk, struct sock *child)
+{
+#if 0
+ struct tcp_bind_hashbucket *head = &tcp_bhash[tcp_bhashfn(child->num)];
+ struct tcp_bind_bucket *tb;
+
+ spin_lock(&head->lock);
+ tb = (struct tcp_bind_bucket *)sk->prev;
+ if ((child->bind_next = tb->owners) != NULL)
+ tb->owners->bind_pprev = &child->bind_next;
+ tb->owners = child;
+ child->bind_pprev = &tb->owners;
+ child->prev = (struct sock *) tb;
+ spin_unlock(&head->lock);
+#endif
+}
+
+__inline__ void tcp_inherit_port(struct sock *sk, struct sock *child)
+{
+#if 0
+ local_bh_disable();
+ __tcp_inherit_port(sk, child);
+ local_bh_enable();
+#endif
+}
+
+static inline void tcp_bind_hash(struct sock *sk, struct tcp_bind_bucket *tb, unsigned short snum)
+{
+#if 0
+ sk->num = snum;
+ if ((sk->bind_next = tb->owners) != NULL)
+ tb->owners->bind_pprev = &sk->bind_next;
+ tb->owners = sk;
+ sk->bind_pprev = &tb->owners;
+ sk->prev = (struct sock *) tb;
+#endif
+}
+
+static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb)
+{
+#if 0
+ struct sock *sk2 = tb->owners;
+ int sk_reuse = sk->reuse;
+
+ for( ; sk2 != NULL; sk2 = sk2->bind_next) {
+ if (sk != sk2 &&
+ sk2->reuse <= 1 &&
+ sk->bound_dev_if == sk2->bound_dev_if) {
+ if (!sk_reuse ||
+ !sk2->reuse ||
+ sk2->state == TCP_LISTEN) {
+ if (!sk2->rcv_saddr ||
+ !sk->rcv_saddr ||
+ (sk2->rcv_saddr == sk->rcv_saddr))
+ break;
+ }
+ }
+ }
+ return sk2 != NULL;
+#else
+ return 0;
+#endif
+}
+
+/* Obtain a reference to a local port for the given sock,
+ * if snum is zero it means select any available local port.
+ */
+static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
+{
+#if 0
+ struct tcp_bind_hashbucket *head;
+ struct tcp_bind_bucket *tb;
+ int ret;
+
+ local_bh_disable();
+ if (snum == 0) {
+ int low = sysctl_local_port_range[0];
+ int high = sysctl_local_port_range[1];
+ int remaining = (high - low) + 1;
+ int rover;
+
+ spin_lock(&tcp_portalloc_lock);
+ rover = tcp_port_rover;
+ do { rover++;
+ if ((rover < low) || (rover > high))
+ rover = low;
+ head = &tcp_bhash[tcp_bhashfn(rover)];
+ spin_lock(&head->lock);
+ for (tb = head->chain; tb; tb = tb->next)
+ if (tb->port == rover)
+ goto next;
+ break;
+ next:
+ spin_unlock(&head->lock);
+ } while (--remaining > 0);
+ tcp_port_rover = rover;
+ spin_unlock(&tcp_portalloc_lock);
+
+ /* Exhausted local port range during search? */
+ ret = 1;
+ if (remaining <= 0)
+ goto fail;
+
+ /* OK, here is the one we will use. HEAD is
+ * non-NULL and we hold it's mutex.
+ */
+ snum = rover;
+ tb = NULL;
+ } else {
+ head = &tcp_bhash[tcp_bhashfn(snum)];
+ spin_lock(&head->lock);
+ for (tb = head->chain; tb != NULL; tb = tb->next)
+ if (tb->port == snum)
+ break;
+ }
+ if (tb != NULL && tb->owners != NULL) {
+ if (sk->reuse > 1)
+ goto success;
+ if (tb->fastreuse > 0 && sk->reuse != 0 && sk->state != TCP_LISTEN) {
+ goto success;
+ } else {
+ ret = 1;
+ if (tcp_bind_conflict(sk, tb))
+ goto fail_unlock;
+ }
+ }
+ ret = 1;
+ if (tb == NULL &&
+ (tb = tcp_bucket_create(head, snum)) == NULL)
+ goto fail_unlock;
+ if (tb->owners == NULL) {
+ if (sk->reuse && sk->state != TCP_LISTEN)
+ tb->fastreuse = 1;
+ else
+ tb->fastreuse = 0;
+ } else if (tb->fastreuse &&
+ ((sk->reuse == 0) || (sk->state == TCP_LISTEN)))
+ tb->fastreuse = 0;
+success:
+ if (sk->prev == NULL)
+ tcp_bind_hash(sk, tb, snum);
+ BUG_TRAP(sk->prev == (struct sock *) tb);
+ ret = 0;
+
+fail_unlock:
+ spin_unlock(&head->lock);
+fail:
+ local_bh_enable();
+ return ret;
+#else
+ return 0;
+#endif
+}
+
+/* Get rid of any references to a local port held by the
+ * given sock.
+ */
+__inline__ void __tcp_put_port(struct sock *sk)
+{
+#if 0
+ struct tcp_bind_hashbucket *head = &tcp_bhash[tcp_bhashfn(sk->num)];
+ struct tcp_bind_bucket *tb;
+
+ spin_lock(&head->lock);
+ tb = (struct tcp_bind_bucket *) sk->prev;
+ if (sk->bind_next)
+ sk->bind_next->bind_pprev = sk->bind_pprev;
+ *(sk->bind_pprev) = sk->bind_next;
+ sk->prev = NULL;
+ sk->num = 0;
+ if (tb->owners == NULL) {
+ if (tb->next)
+ tb->next->pprev = tb->pprev;
+ *(tb->pprev) = tb->next;
+ kmem_cache_free(tcp_bucket_cachep, tb);
+ }
+ spin_unlock(&head->lock);
+#endif
+}
+
+void tcp_put_port(struct sock *sk)
+{
+#if 0
+ local_bh_disable();
+ __tcp_put_port(sk);
+ local_bh_enable();
+#endif
+}
+
+/* This lock without WQ_FLAG_EXCLUSIVE is good on UP and it can be very bad on SMP.
+ * Look, when several writers sleep and reader wakes them up, all but one
+ * immediately hit write lock and grab all the cpus. Exclusive sleep solves
+ * this, _but_ remember, it adds useless work on UP machines (wake up each
+ * exclusive lock release). It should be ifdefed really.
+ */
+
+void tcp_listen_wlock(void)
+{
+#if 0
+ write_lock(&tcp_lhash_lock);
+
+ if (atomic_read(&tcp_lhash_users)) {
+ DECLARE_WAITQUEUE(wait, current);
+
+ add_wait_queue_exclusive(&tcp_lhash_wait, &wait);
+ for (;;) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ if (atomic_read(&tcp_lhash_users) == 0)
+ break;
+ write_unlock_bh(&tcp_lhash_lock);
+ schedule();
+ write_lock_bh(&tcp_lhash_lock);
+ }
+
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&tcp_lhash_wait, &wait);
+ }
+#endif
+}
+
+static __inline__ void __tcp_v4_hash(struct sock *sk, const int listen_possible)
+{
+#if 0
+ struct sock **skp;
+ rwlock_t *lock;
+
+ BUG_TRAP(sk->pprev==NULL);
+ if(listen_possible && sk->state == TCP_LISTEN) {
+ skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
+ lock = &tcp_lhash_lock;
+ tcp_listen_wlock();
+ } else {
+ skp = &tcp_ehash[(sk->hashent = tcp_sk_hashfn(sk))].chain;
+ lock = &tcp_ehash[sk->hashent].lock;
+ write_lock(lock);
+ }
+ if((sk->next = *skp) != NULL)
+ (*skp)->pprev = &sk->next;
+ *skp = sk;
+ sk->pprev = skp;
+ sock_prot_inc_use(sk->prot);
+ write_unlock(lock);
+ if (listen_possible && sk->state == TCP_LISTEN)
+ wake_up(&tcp_lhash_wait);
+#endif
+}
+
+static void tcp_v4_hash(struct sock *sk)
+{
+#if 0
+ if (sk->state != TCP_CLOSE) {
+ local_bh_disable();
+ __tcp_v4_hash(sk, 1);
+ local_bh_enable();
+ }
+#endif
+}
+
+void tcp_unhash(struct sock *sk)
+{
+#if 0
+ rwlock_t *lock;
+
+ if (!sk->pprev)
+ goto ende;
+
+ if (sk->state == TCP_LISTEN) {
+ local_bh_disable();
+ tcp_listen_wlock();
+ lock = &tcp_lhash_lock;
+ } else {
+ struct tcp_ehash_bucket *head = &tcp_ehash[sk->hashent];
+ lock = &head->lock;
+ write_lock_bh(&head->lock);
+ }
+
+ if(sk->pprev) {
+ if(sk->next)
+ sk->next->pprev = sk->pprev;
+ *sk->pprev = sk->next;
+ sk->pprev = NULL;
+ sock_prot_dec_use(sk->prot);
+ }
+ write_unlock_bh(lock);
+
+ ende:
+ if (sk->state == TCP_LISTEN)
+ wake_up(&tcp_lhash_wait);
+#endif
+}
+
+/* Don't inline this cruft. Here are some nice properties to
+ * exploit here. The BSD API does not allow a listening TCP
+ * to specify the remote port nor the remote address for the
+ * connection. So always assume those are both wildcarded
+ * during the search since they can never be otherwise.
+ */
+static struct sock *__tcp_v4_lookup_listener(struct sock *sk, u32 daddr, unsigned short hnum, int dif)
+{
+#if 0
+ struct sock *result = NULL;
+ int score, hiscore;
+
+ hiscore=0;
+ for(; sk; sk = sk->next) {
+ if(sk->num == hnum) {
+ __u32 rcv_saddr = sk->rcv_saddr;
+
+ score = 1;
+ if(rcv_saddr) {
+ if (rcv_saddr != daddr)
+ continue;
+ score++;
+ }
+ if (sk->bound_dev_if) {
+ if (sk->bound_dev_if != dif)
+ continue;
+ score++;
+ }
+ if (score == 3)
+ return sk;
+ if (score > hiscore) {
+ hiscore = score;
+ result = sk;
+ }
+ }
+ }
+ return result;
+#else
+ return NULL;
+#endif
+}
+
+/* Optimize the common listener case. */
+__inline__ struct sock *tcp_v4_lookup_listener(u32 daddr, unsigned short hnum, int dif)
+{
+#if 0
+ struct sock *sk;
+
+ read_lock(&tcp_lhash_lock);
+ sk = tcp_listening_hash[tcp_lhashfn(hnum)];
+ if (sk) {
+ if (sk->num == hnum &&
+ sk->next == NULL &&
+ (!sk->rcv_saddr || sk->rcv_saddr == daddr) &&
+ !sk->bound_dev_if)
+ goto sherry_cache;
+ sk = __tcp_v4_lookup_listener(sk, daddr, hnum, dif);
+ }
+ if (sk) {
+sherry_cache:
+ sock_hold(sk);
+ }
+ read_unlock(&tcp_lhash_lock);
+ return sk;
+#else
+ return NULL;
+#endif
+}
+
+/* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
+ * we need not check it for TCP lookups anymore, thanks Alexey. -DaveM
+ *
+ * Local BH must be disabled here.
+ */
+
+static inline struct sock *__tcp_v4_lookup_established(u32 saddr, u16 sport,
+ u32 daddr, u16 hnum, int dif)
+{
+#if 0
+ struct tcp_ehash_bucket *head;
+ TCP_V4_ADDR_COOKIE(acookie, saddr, daddr)
+ __u32 ports = TCP_COMBINED_PORTS(sport, hnum);
+ struct sock *sk;
+ int hash;
+
+ /* Optimize here for direct hit, only listening connections can
+ * have wildcards anyways.
+ */
+ hash = tcp_hashfn(daddr, hnum, saddr, sport);
+ head = &tcp_ehash[hash];
+ read_lock(&head->lock);
+ for(sk = head->chain; sk; sk = sk->next) {
+ if(TCP_IPV4_MATCH(sk, acookie, saddr, daddr, ports, dif))
+ goto hit; /* You sunk my battleship! */
+ }
+
+ /* Must check for a TIME_WAIT'er before going to listener hash. */
+ for(sk = (head + tcp_ehash_size)->chain; sk; sk = sk->next)
+ if(TCP_IPV4_MATCH(sk, acookie, saddr, daddr, ports, dif))
+ goto hit;
+ read_unlock(&head->lock);
+
+ return NULL;
+
+hit:
+ sock_hold(sk);
+ read_unlock(&head->lock);
+ return sk;
+#else
+ return NULL;
+#endif
+}
+
+static inline struct sock *__tcp_v4_lookup(u32 saddr, u16 sport,
+ u32 daddr, u16 hnum, int dif)
+{
+#if 0
+ struct sock *sk;
+
+ sk = __tcp_v4_lookup_established(saddr, sport, daddr, hnum, dif);
+
+ if (sk)
+ return sk;
+
+ return tcp_v4_lookup_listener(daddr, hnum, dif);
+#else
+ return NULL;
+#endif
+}
+
+__inline__ struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif)
+{
+#if 0
+ struct sock *sk;
+
+ local_bh_disable();
+ sk = __tcp_v4_lookup(saddr, sport, daddr, ntohs(dport), dif);
+ local_bh_enable();
+
+ return sk;
+#else
+ return NULL;
+#endif
+}
+
+static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+ return secure_tcp_sequence_number(skb->nh.iph->daddr,
+ skb->nh.iph->saddr,
+ skb->h.th->dest,
+ skb->h.th->source);
+#else
+ return 0;
+#endif
+}
+
+/* called with local bh disabled */
+static int __tcp_v4_check_established(struct sock *sk, __u16 lport,
+ struct tcp_tw_bucket **twp)
+{
+#if 0
+ u32 daddr = sk->rcv_saddr;
+ u32 saddr = sk->daddr;
+ int dif = sk->bound_dev_if;
+ TCP_V4_ADDR_COOKIE(acookie, saddr, daddr)
+ __u32 ports = TCP_COMBINED_PORTS(sk->dport, lport);
+ int hash = tcp_hashfn(daddr, lport, saddr, sk->dport);
+ struct tcp_ehash_bucket *head = &tcp_ehash[hash];
+ struct sock *sk2, **skp;
+ struct tcp_tw_bucket *tw;
+
+ write_lock(&head->lock);
+
+ /* Check TIME-WAIT sockets first. */
+ for(skp = &(head + tcp_ehash_size)->chain; (sk2=*skp) != NULL;
+ skp = &sk2->next) {
+ tw = (struct tcp_tw_bucket*)sk2;
+
+ if(TCP_IPV4_MATCH(sk2, acookie, saddr, daddr, ports, dif)) {
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ /* With PAWS, it is safe from the viewpoint
+ of data integrity. Even without PAWS it
+ is safe provided sequence spaces do not
+ overlap i.e. at data rates <= 80Mbit/sec.
+
+ Actually, the idea is close to VJ's one,
+ only timestamp cache is held not per host,
+ but per port pair and TW bucket is used
+ as state holder.
+
+ If TW bucket has been already destroyed we
+ fall back to VJ's scheme and use initial
+ timestamp retrieved from peer table.
+ */
+ if (tw->ts_recent_stamp &&
+ (!twp || (sysctl_tcp_tw_reuse &&
+ xtime.tv_sec - tw->ts_recent_stamp > 1))) {
+ if ((tp->write_seq = tw->snd_nxt+65535+2) == 0)
+ tp->write_seq = 1;
+ tp->ts_recent = tw->ts_recent;
+ tp->ts_recent_stamp = tw->ts_recent_stamp;
+ sock_hold(sk2);
+ skp = &head->chain;
+ goto unique;
+ } else
+ goto not_unique;
+ }
+ }
+ tw = NULL;
+
+ /* And established part... */
+ for(skp = &head->chain; (sk2=*skp)!=NULL; skp = &sk2->next) {
+ if(TCP_IPV4_MATCH(sk2, acookie, saddr, daddr, ports, dif))
+ goto not_unique;
+ }
+
+unique:
+ /* Must record num and sport now. Otherwise we will see
+ * in hash table socket with a funny identity. */
+ sk->num = lport;
+ sk->sport = htons(lport);
+ BUG_TRAP(sk->pprev==NULL);
+ if ((sk->next = *skp) != NULL)
+ (*skp)->pprev = &sk->next;
+
+ *skp = sk;
+ sk->pprev = skp;
+ sk->hashent = hash;
+ sock_prot_inc_use(sk->prot);
+ write_unlock(&head->lock);
+
+ if (twp) {
+ *twp = tw;
+ NET_INC_STATS_BH(TimeWaitRecycled);
+ } else if (tw) {
+ /* Silly. Should hash-dance instead... */
+ tcp_tw_deschedule(tw);
+ tcp_timewait_kill(tw);
+ NET_INC_STATS_BH(TimeWaitRecycled);
+
+ tcp_tw_put(tw);
+ }
+
+ return 0;
+
+not_unique:
+ write_unlock(&head->lock);
+ return -EADDRNOTAVAIL;
+#else
+ return 0;
+#endif
+}
+
+/*
+ * Bind a port for a connect operation and hash it.
+ */
+static int tcp_v4_hash_connect(struct sock *sk)
+{
+#if 0
+ unsigned short snum = sk->num;
+ struct tcp_bind_hashbucket *head;
+ struct tcp_bind_bucket *tb;
+
+ if (snum == 0) {
+ int rover;
+ int low = sysctl_local_port_range[0];
+ int high = sysctl_local_port_range[1];
+ int remaining = (high - low) + 1;
+ struct tcp_tw_bucket *tw = NULL;
+
+ local_bh_disable();
+
+ /* TODO. Actually it is not so bad idea to remove
+ * tcp_portalloc_lock before next submission to Linus.
+ * As soon as we touch this place at all it is time to think.
+ *
+ * Now it protects single _advisory_ variable tcp_port_rover,
+ * hence it is mostly useless.
+ * Code will work nicely if we just delete it, but
+ * I am afraid in contented case it will work not better or
+ * even worse: another cpu just will hit the same bucket
+ * and spin there.
+ * So some cpu salt could remove both contention and
+ * memory pingpong. Any ideas how to do this in a nice way?
+ */
+ spin_lock(&tcp_portalloc_lock);
+ rover = tcp_port_rover;
+
+ do {
+ rover++;
+ if ((rover < low) || (rover > high))
+ rover = low;
+ head = &tcp_bhash[tcp_bhashfn(rover)];
+ spin_lock(&head->lock);
+
+ /* Does not bother with rcv_saddr checks,
+ * because the established check is already
+ * unique enough.
+ */
+ for (tb = head->chain; tb; tb = tb->next) {
+ if (tb->port == rover) {
+ BUG_TRAP(tb->owners != NULL);
+ if (tb->fastreuse >= 0)
+ goto next_port;
+ if (!__tcp_v4_check_established(sk, rover, &tw))
+ goto ok;
+ goto next_port;
+ }
+ }
+
+ tb = tcp_bucket_create(head, rover);
+ if (!tb) {
+ spin_unlock(&head->lock);
+ break;
+ }
+ tb->fastreuse = -1;
+ goto ok;
+
+ next_port:
+ spin_unlock(&head->lock);
+ } while (--remaining > 0);
+ tcp_port_rover = rover;
+ spin_unlock(&tcp_portalloc_lock);
+
+ local_bh_enable();
+
+ return -EADDRNOTAVAIL;
+
+ ok:
+ /* All locks still held and bhs disabled */
+ tcp_port_rover = rover;
+ spin_unlock(&tcp_portalloc_lock);
+
+ tcp_bind_hash(sk, tb, rover);
+ if (!sk->pprev) {
+ sk->sport = htons(rover);
+ __tcp_v4_hash(sk, 0);
+ }
+ spin_unlock(&head->lock);
+
+ if (tw) {
+ tcp_tw_deschedule(tw);
+ tcp_timewait_kill(tw);
+ tcp_tw_put(tw);
+ }
+
+ local_bh_enable();
+ return 0;
+ }
+
+ head = &tcp_bhash[tcp_bhashfn(snum)];
+ tb = (struct tcp_bind_bucket *)sk->prev;
+ spin_lock_bh(&head->lock);
+ if (tb->owners == sk && sk->bind_next == NULL) {
+ __tcp_v4_hash(sk, 0);
+ spin_unlock_bh(&head->lock);
+ return 0;
+ } else {
+ int ret;
+ spin_unlock(&head->lock);
+ /* No definite answer... Walk to established hash table */
+ ret = __tcp_v4_check_established(sk, snum, NULL);
+ local_bh_enable();
+ return ret;
+ }
+#else
+ return 0;
+#endif
+}
+
+/* This will initiate an outgoing connection. */
+int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sockaddr_in *usin = (struct sockaddr_in *) uaddr;
+ struct rtable *rt;
+ u32 daddr, nexthop;
+ int tmp;
+ int err;
+
+ if (addr_len < sizeof(struct sockaddr_in))
+ return(-EINVAL);
+
+ if (usin->sin_family != AF_INET)
+ return(-EAFNOSUPPORT);
+
+ nexthop = daddr = usin->sin_addr.s_addr;
+ if (sk->protinfo.af_inet.opt && sk->protinfo.af_inet.opt->srr) {
+ if (daddr == 0)
+ return -EINVAL;
+ nexthop = sk->protinfo.af_inet.opt->faddr;
+ }
+
+ tmp = ip_route_connect(&rt, nexthop, sk->saddr,
+ RT_CONN_FLAGS(sk), sk->bound_dev_if);
+ if (tmp < 0)
+ return tmp;
+
+ if (rt->rt_flags&(RTCF_MULTICAST|RTCF_BROADCAST)) {
+ ip_rt_put(rt);
+ return -ENETUNREACH;
+ }
+
+ __sk_dst_set(sk, &rt->u.dst);
+ sk->route_caps = rt->u.dst.dev->features;
+
+ if (!sk->protinfo.af_inet.opt || !sk->protinfo.af_inet.opt->srr)
+ daddr = rt->rt_dst;
+
+ if (!sk->saddr)
+ sk->saddr = rt->rt_src;
+ sk->rcv_saddr = sk->saddr;
+
+ if (tp->ts_recent_stamp && sk->daddr != daddr) {
+ /* Reset inherited state */
+ tp->ts_recent = 0;
+ tp->ts_recent_stamp = 0;
+ tp->write_seq = 0;
+ }
+
+ if (sysctl_tcp_tw_recycle &&
+ !tp->ts_recent_stamp &&
+ rt->rt_dst == daddr) {
+ struct inet_peer *peer = rt_get_peer(rt);
+
+ /* VJ's idea. We save last timestamp seen from
+ * the destination in peer table, when entering state TIME-WAIT
+ * and initialize ts_recent from it, when trying new connection.
+ */
+
+ if (peer && peer->tcp_ts_stamp + TCP_PAWS_MSL >= xtime.tv_sec) {
+ tp->ts_recent_stamp = peer->tcp_ts_stamp;
+ tp->ts_recent = peer->tcp_ts;
+ }
+ }
+
+ sk->dport = usin->sin_port;
+ sk->daddr = daddr;
+
+ tp->ext_header_len = 0;
+ if (sk->protinfo.af_inet.opt)
+ tp->ext_header_len = sk->protinfo.af_inet.opt->optlen;
+
+ tp->mss_clamp = 536;
+
+ /* Socket identity is still unknown (sport may be zero).
+ * However we set state to SYN-SENT and not releasing socket
+ * lock select source port, enter ourselves into the hash tables and
+ * complete initalization after this.
+ */
+ tcp_set_state(sk, TCP_SYN_SENT);
+ err = tcp_v4_hash_connect(sk);
+ if (err)
+ goto failure;
+
+ if (!tp->write_seq)
+ tp->write_seq = secure_tcp_sequence_number(sk->saddr, sk->daddr,
+ sk->sport, usin->sin_port);
+
+ sk->protinfo.af_inet.id = tp->write_seq^jiffies;
+
+ err = tcp_connect(sk);
+ if (err)
+ goto failure;
+
+ return 0;
+
+failure:
+ tcp_set_state(sk, TCP_CLOSE);
+ __sk_dst_reset(sk);
+ sk->route_caps = 0;
+ sk->dport = 0;
+ return err;
+#else
+ return 0;
+#endif
+}
+
+static __inline__ int tcp_v4_iif(struct sk_buff *skb)
+{
+#if 0
+ return ((struct rtable*)skb->dst)->rt_iif;
+#else
+ return 0;
+#endif
+}
+
+static __inline__ unsigned tcp_v4_synq_hash(u32 raddr, u16 rport)
+{
+#if 0
+ unsigned h = raddr ^ rport;
+ h ^= h>>16;
+ h ^= h>>8;
+ return h&(TCP_SYNQ_HSIZE-1);
+#else
+ return 0;
+#endif
+}
+
+static struct open_request *tcp_v4_search_req(struct tcp_opt *tp,
+ struct open_request ***prevp,
+ __u16 rport,
+ __u32 raddr, __u32 laddr)
+{
+#if 0
+ struct tcp_listen_opt *lopt = tp->listen_opt;
+ struct open_request *req, **prev;
+
+ for (prev = &lopt->syn_table[tcp_v4_synq_hash(raddr, rport)];
+ (req = *prev) != NULL;
+ prev = &req->dl_next) {
+ if (req->rmt_port == rport &&
+ req->af.v4_req.rmt_addr == raddr &&
+ req->af.v4_req.loc_addr == laddr &&
+ TCP_INET_FAMILY(req->class->family)) {
+ BUG_TRAP(req->sk == NULL);
+ *prevp = prev;
+ return req;
+ }
+ }
+
+ return NULL;
+#else
+ return NULL;
+#endif
+}
+
+static void tcp_v4_synq_add(struct sock *sk, struct open_request *req)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ struct tcp_listen_opt *lopt = tp->listen_opt;
+ unsigned h = tcp_v4_synq_hash(req->af.v4_req.rmt_addr, req->rmt_port);
+
+ req->expires = jiffies + TCP_TIMEOUT_INIT;
+ req->retrans = 0;
+ req->sk = NULL;
+ req->dl_next = lopt->syn_table[h];
+
+ write_lock(&tp->syn_wait_lock);
+ lopt->syn_table[h] = req;
+ write_unlock(&tp->syn_wait_lock);
+
+ tcp_synq_added(sk);
+#endif
+}
+
+
+/*
+ * This routine does path mtu discovery as defined in RFC1191.
+ */
+static inline void do_pmtu_discovery(struct sock *sk, struct iphdr *ip, unsigned mtu)
+{
+#if 0
+ struct dst_entry *dst;
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ /* We are not interested in TCP_LISTEN and open_requests (SYN-ACKs
+ * send out by Linux are always <576bytes so they should go through
+ * unfragmented).
+ */
+ if (sk->state == TCP_LISTEN)
+ return;
+
+ /* We don't check in the destentry if pmtu discovery is forbidden
+ * on this route. We just assume that no packet_to_big packets
+ * are send back when pmtu discovery is not active.
+ * There is a small race when the user changes this flag in the
+ * route, but I think that's acceptable.
+ */
+ if ((dst = __sk_dst_check(sk, 0)) == NULL)
+ return;
+
+ ip_rt_update_pmtu(dst, mtu);
+
+ /* Something is about to be wrong... Remember soft error
+ * for the case, if this connection will not able to recover.
+ */
+ if (mtu < dst->pmtu && ip_dont_fragment(sk, dst))
+ sk->err_soft = EMSGSIZE;
+
+ if (sk->protinfo.af_inet.pmtudisc != IP_PMTUDISC_DONT &&
+ tp->pmtu_cookie > dst->pmtu) {
+ tcp_sync_mss(sk, dst->pmtu);
+
+ /* Resend the TCP packet because it's
+ * clear that the old packet has been
+ * dropped. This is the new "fast" path mtu
+ * discovery.
+ */
+ tcp_simple_retransmit(sk);
+ } /* else let the usual retransmit timer handle it */
+#endif
+}
+
+/*
+ * This routine is called by the ICMP module when it gets some
+ * sort of error condition. If err < 0 then the socket should
+ * be closed and the error returned to the user. If err > 0
+ * it's just the icmp type << 8 | icmp code. After adjustment
+ * header points to the first 8 bytes of the tcp header. We need
+ * to find the appropriate port.
+ *
+ * The locking strategy used here is very "optimistic". When
+ * someone else accesses the socket the ICMP is just dropped
+ * and for some paths there is no check at all.
+ * A more general error queue to queue errors for later handling
+ * is probably better.
+ *
+ */
+
+void tcp_v4_err(struct sk_buff *skb, u32 info)
+{
+#if 0
+ struct iphdr *iph = (struct iphdr*)skb->data;
+ struct tcphdr *th = (struct tcphdr*)(skb->data+(iph->ihl<<2));
+ struct tcp_opt *tp;
+ int type = skb->h.icmph->type;
+ int code = skb->h.icmph->code;
+ struct sock *sk;
+ __u32 seq;
+ int err;
+
+ if (skb->len < (iph->ihl << 2) + 8) {
+ ICMP_INC_STATS_BH(IcmpInErrors);
+ return;
+ }
+
+ sk = tcp_v4_lookup(iph->daddr, th->dest, iph->saddr, th->source, tcp_v4_iif(skb));
+ if (sk == NULL) {
+ ICMP_INC_STATS_BH(IcmpInErrors);
+ return;
+ }
+ if (sk->state == TCP_TIME_WAIT) {
+ tcp_tw_put((struct tcp_tw_bucket*)sk);
+ return;
+ }
+
+ bh_lock_sock(sk);
+ /* If too many ICMPs get dropped on busy
+ * servers this needs to be solved differently.
+ */
+ if (sk->lock.users != 0)
+ NET_INC_STATS_BH(LockDroppedIcmps);
+
+ if (sk->state == TCP_CLOSE)
+ goto out;
+
+ tp = &sk->tp_pinfo.af_tcp;
+ seq = ntohl(th->seq);
+ if (sk->state != TCP_LISTEN && !between(seq, tp->snd_una, tp->snd_nxt)) {
+ NET_INC_STATS(OutOfWindowIcmps);
+ goto out;
+ }
+
+ switch (type) {
+ case ICMP_SOURCE_QUENCH:
+ /* This is deprecated, but if someone generated it,
+ * we have no reasons to ignore it.
+ */
+ if (sk->lock.users == 0)
+ tcp_enter_cwr(tp);
+ goto out;
+ case ICMP_PARAMETERPROB:
+ err = EPROTO;
+ break;
+ case ICMP_DEST_UNREACH:
+ if (code > NR_ICMP_UNREACH)
+ goto out;
+
+ if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */
+ if (sk->lock.users == 0)
+ do_pmtu_discovery(sk, iph, info);
+ goto out;
+ }
+
+ err = icmp_err_convert[code].errno;
+ break;
+ case ICMP_TIME_EXCEEDED:
+ err = EHOSTUNREACH;
+ break;
+ default:
+ goto out;
+ }
+
+ switch (sk->state) {
+ struct open_request *req, **prev;
+ case TCP_LISTEN:
+ if (sk->lock.users != 0)
+ goto out;
+
+ req = tcp_v4_search_req(tp, &prev,
+ th->dest,
+ iph->daddr, iph->saddr);
+ if (!req)
+ goto out;
+
+ /* ICMPs are not backlogged, hence we cannot get
+ an established socket here.
+ */
+ BUG_TRAP(req->sk == NULL);
+
+ if (seq != req->snt_isn) {
+ NET_INC_STATS_BH(OutOfWindowIcmps);
+ goto out;
+ }
+
+ /*
+ * Still in SYN_RECV, just remove it silently.
+ * There is no good way to pass the error to the newly
+ * created socket, and POSIX does not want network
+ * errors returned from accept().
+ */
+ tcp_synq_drop(sk, req, prev);
+ goto out;
+
+ case TCP_SYN_SENT:
+ case TCP_SYN_RECV: /* Cannot happen.
+ It can f.e. if SYNs crossed.
+ */
+ if (sk->lock.users == 0) {
+ TCP_INC_STATS_BH(TcpAttemptFails);
+ sk->err = err;
+
+ sk->error_report(sk);
+
+ tcp_done(sk);
+ } else {
+ sk->err_soft = err;
+ }
+ goto out;
+ }
+
+ /* If we've already connected we will keep trying
+ * until we time out, or the user gives up.
+ *
+ * rfc1122 4.2.3.9 allows to consider as hard errors
+ * only PROTO_UNREACH and PORT_UNREACH (well, FRAG_FAILED too,
+ * but it is obsoleted by pmtu discovery).
+ *
+ * Note, that in modern internet, where routing is unreliable
+ * and in each dark corner broken firewalls sit, sending random
+ * errors ordered by their masters even this two messages finally lose
+ * their original sense (even Linux sends invalid PORT_UNREACHs)
+ *
+ * Now we are in compliance with RFCs.
+ * --ANK (980905)
+ */
+
+ if (sk->lock.users == 0 && sk->protinfo.af_inet.recverr) {
+ sk->err = err;
+ sk->error_report(sk);
+ } else { /* Only an error on timeout */
+ sk->err_soft = err;
+ }
+
+out:
+ bh_unlock_sock(sk);
+ sock_put(sk);
+#endif
+}
+
+/* This routine computes an IPv4 TCP checksum. */
+void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len,
+ struct sk_buff *skb)
+{
+#if 0
+ if (skb->ip_summed == CHECKSUM_HW) {
+ th->check = ~tcp_v4_check(th, len, sk->saddr, sk->daddr, 0);
+ skb->csum = offsetof(struct tcphdr, check);
+ } else {
+ th->check = tcp_v4_check(th, len, sk->saddr, sk->daddr,
+ csum_partial((char *)th, th->doff<<2, skb->csum));
+ }
+#endif
+}
+
+/*
+ * This routine will send an RST to the other tcp.
+ *
+ * Someone asks: why I NEVER use socket parameters (TOS, TTL etc.)
+ * for reset.
+ * Answer: if a packet caused RST, it is not for a socket
+ * existing in our system, if it is matched to a socket,
+ * it is just duplicate segment or bug in other side's TCP.
+ * So that we build reply only basing on parameters
+ * arrived with segment.
+ * Exception: precedence violation. We do not implement it in any case.
+ */
+
+static void tcp_v4_send_reset(struct sk_buff *skb)
+{
+#if 0
+ struct tcphdr *th = skb->h.th;
+ struct tcphdr rth;
+ struct ip_reply_arg arg;
+
+ /* Never send a reset in response to a reset. */
+ if (th->rst)
+ return;
+
+ if (((struct rtable*)skb->dst)->rt_type != RTN_LOCAL)
+ return;
+
+ /* Swap the send and the receive. */
+ memset(&rth, 0, sizeof(struct tcphdr));
+ rth.dest = th->source;
+ rth.source = th->dest;
+ rth.doff = sizeof(struct tcphdr)/4;
+ rth.rst = 1;
+
+ if (th->ack) {
+ rth.seq = th->ack_seq;
+ } else {
+ rth.ack = 1;
+ rth.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin
+ + skb->len - (th->doff<<2));
+ }
+
+ memset(&arg, 0, sizeof arg);
+ arg.iov[0].iov_base = (unsigned char *)&rth;
+ arg.iov[0].iov_len = sizeof rth;
+ arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr,
+ skb->nh.iph->saddr, /*XXX*/
+ sizeof(struct tcphdr),
+ IPPROTO_TCP,
+ 0);
+ arg.n_iov = 1;
+ arg.csumoffset = offsetof(struct tcphdr, check) / 2;
+
+ tcp_socket->sk->protinfo.af_inet.ttl = sysctl_ip_default_ttl;
+ ip_send_reply(tcp_socket->sk, skb, &arg, sizeof rth);
+
+ TCP_INC_STATS_BH(TcpOutSegs);
+ TCP_INC_STATS_BH(TcpOutRsts);
+#endif
+}
+
+/* The code following below sending ACKs in SYN-RECV and TIME-WAIT states
+ outside socket context is ugly, certainly. What can I do?
+ */
+
+static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts)
+{
+#if 0
+ struct tcphdr *th = skb->h.th;
+ struct {
+ struct tcphdr th;
+ u32 tsopt[3];
+ } rep;
+ struct ip_reply_arg arg;
+
+ memset(&rep.th, 0, sizeof(struct tcphdr));
+ memset(&arg, 0, sizeof arg);
+
+ arg.iov[0].iov_base = (unsigned char *)&rep;
+ arg.iov[0].iov_len = sizeof(rep.th);
+ arg.n_iov = 1;
+ if (ts) {
+ rep.tsopt[0] = htonl((TCPOPT_NOP << 24) |
+ (TCPOPT_NOP << 16) |
+ (TCPOPT_TIMESTAMP << 8) |
+ TCPOLEN_TIMESTAMP);
+ rep.tsopt[1] = htonl(tcp_time_stamp);
+ rep.tsopt[2] = htonl(ts);
+ arg.iov[0].iov_len = sizeof(rep);
+ }
+
+ /* Swap the send and the receive. */
+ rep.th.dest = th->source;
+ rep.th.source = th->dest;
+ rep.th.doff = arg.iov[0].iov_len/4;
+ rep.th.seq = htonl(seq);
+ rep.th.ack_seq = htonl(ack);
+ rep.th.ack = 1;
+ rep.th.window = htons(win);
+
+ arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr,
+ skb->nh.iph->saddr, /*XXX*/
+ arg.iov[0].iov_len,
+ IPPROTO_TCP,
+ 0);
+ arg.csumoffset = offsetof(struct tcphdr, check) / 2;
+
+ ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
+
+ TCP_INC_STATS_BH(TcpOutSegs);
+#endif
+}
+
+static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+ struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sk;
+
+ tcp_v4_send_ack(skb, tw->snd_nxt, tw->rcv_nxt,
+ tw->rcv_wnd>>tw->rcv_wscale, tw->ts_recent);
+
+ tcp_tw_put(tw);
+#endif
+}
+
+static void tcp_v4_or_send_ack(struct sk_buff *skb, struct open_request *req)
+{
+#if 0
+ tcp_v4_send_ack(skb, req->snt_isn+1, req->rcv_isn+1, req->rcv_wnd,
+ req->ts_recent);
+#endif
+}
+
+static struct dst_entry* tcp_v4_route_req(struct sock *sk, struct open_request *req)
+{
+#if 0
+ struct rtable *rt;
+ struct ip_options *opt;
+
+ opt = req->af.v4_req.opt;
+ if(ip_route_output(&rt, ((opt && opt->srr) ?
+ opt->faddr :
+ req->af.v4_req.rmt_addr),
+ req->af.v4_req.loc_addr,
+ RT_CONN_FLAGS(sk), sk->bound_dev_if)) {
+ IP_INC_STATS_BH(IpOutNoRoutes);
+ return NULL;
+ }
+ if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) {
+ ip_rt_put(rt);
+ IP_INC_STATS_BH(IpOutNoRoutes);
+ return NULL;
+ }
+ return &rt->u.dst;
+#else
+ return NULL;
+#endif
+}
+
+/*
+ * Send a SYN-ACK after having received an ACK.
+ * This still operates on a open_request only, not on a big
+ * socket.
+ */
+static int tcp_v4_send_synack(struct sock *sk, struct open_request *req,
+ struct dst_entry *dst)
+{
+#if 0
+ int err = -1;
+ struct sk_buff * skb;
+
+ /* First, grab a route. */
+ if (dst == NULL &&
+ (dst = tcp_v4_route_req(sk, req)) == NULL)
+ goto out;
+
+ skb = tcp_make_synack(sk, dst, req);
+
+ if (skb) {
+ struct tcphdr *th = skb->h.th;
+
+ th->check = tcp_v4_check(th, skb->len,
+ req->af.v4_req.loc_addr, req->af.v4_req.rmt_addr,
+ csum_partial((char *)th, skb->len, skb->csum));
+
+ err = ip_build_and_send_pkt(skb, sk, req->af.v4_req.loc_addr,
+ req->af.v4_req.rmt_addr, req->af.v4_req.opt);
+ if (err == NET_XMIT_CN)
+ err = 0;
+ }
+
+out:
+ dst_release(dst);
+ return err;
+#else
+ return 0;
+#endif
+}
+
+/*
+ * IPv4 open_request destructor.
+ */
+static void tcp_v4_or_free(struct open_request *req)
+{
+#if 0
+ if (req->af.v4_req.opt)
+ kfree(req->af.v4_req.opt);
+#endif
+}
+
+static inline void syn_flood_warning(struct sk_buff *skb)
+{
+#if 0
+ static unsigned long warntime;
+
+ if (jiffies - warntime > HZ*60) {
+ warntime = jiffies;
+ printk(KERN_INFO
+ "possible SYN flooding on port %d. Sending cookies.\n",
+ ntohs(skb->h.th->dest));
+ }
+#endif
+}
+
+/*
+ * Save and compile IPv4 options into the open_request if needed.
+ */
+static inline struct ip_options *
+tcp_v4_save_options(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+ struct ip_options *opt = &(IPCB(skb)->opt);
+ struct ip_options *dopt = NULL;
+
+ if (opt && opt->optlen) {
+ int opt_size = optlength(opt);
+ dopt = kmalloc(opt_size, GFP_ATOMIC);
+ if (dopt) {
+ if (ip_options_echo(dopt, skb)) {
+ kfree(dopt);
+ dopt = NULL;
+ }
+ }
+ }
+ return dopt;
+#else
+ return NULL;
+#endif
+}
+
+/*
+ * Maximum number of SYN_RECV sockets in queue per LISTEN socket.
+ * One SYN_RECV socket costs about 80bytes on a 32bit machine.
+ * It would be better to replace it with a global counter for all sockets
+ * but then some measure against one socket starving all other sockets
+ * would be needed.
+ *
+ * It was 128 by default. Experiments with real servers show, that
+ * it is absolutely not enough even at 100conn/sec. 256 cures most
+ * of problems. This value is adjusted to 128 for very small machines
+ * (<=32Mb of memory) and to 1024 on normal or better ones (>=256Mb).
+ * Further increasing requires to change hash table size.
+ */
+int sysctl_max_syn_backlog = 256;
+
+#if 0
+struct or_calltable or_ipv4 = {
+ PF_INET,
+ tcp_v4_send_synack,
+ tcp_v4_or_send_ack,
+ tcp_v4_or_free,
+ tcp_v4_send_reset
+};
+#endif
+
+int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+ struct tcp_opt tp;
+ struct open_request *req;
+ __u32 saddr = skb->nh.iph->saddr;
+ __u32 daddr = skb->nh.iph->daddr;
+ __u32 isn = TCP_SKB_CB(skb)->when;
+ struct dst_entry *dst = NULL;
+#ifdef CONFIG_SYN_COOKIES
+ int want_cookie = 0;
+#else
+#define want_cookie 0 /* Argh, why doesn't gcc optimize this :( */
+#endif
+
+ /* Never answer to SYNs send to broadcast or multicast */
+ if (((struct rtable *)skb->dst)->rt_flags &
+ (RTCF_BROADCAST|RTCF_MULTICAST))
+ goto drop;
+
+ /* TW buckets are converted to open requests without
+ * limitations, they conserve resources and peer is
+ * evidently real one.
+ */
+ if (tcp_synq_is_full(sk) && !isn) {
+#ifdef CONFIG_SYN_COOKIES
+ if (sysctl_tcp_syncookies) {
+ want_cookie = 1;
+ } else
+#endif
+ goto drop;
+ }
+
+ /* Accept backlog is full. If we have already queued enough
+ * of warm entries in syn queue, drop request. It is better than
+ * clogging syn queue with openreqs with exponentially increasing
+ * timeout.
+ */
+ if (tcp_acceptq_is_full(sk) && tcp_synq_young(sk) > 1)
+ goto drop;
+
+ req = tcp_openreq_alloc();
+ if (req == NULL)
+ goto drop;
+
+ tcp_clear_options(&tp);
+ tp.mss_clamp = 536;
+ tp.user_mss = sk->tp_pinfo.af_tcp.user_mss;
+
+ tcp_parse_options(skb, &tp, 0);
+
+ if (want_cookie) {
+ tcp_clear_options(&tp);
+ tp.saw_tstamp = 0;
+ }
+
+ if (tp.saw_tstamp && tp.rcv_tsval == 0) {
+ /* Some OSes (unknown ones, but I see them on web server, which
+ * contains information interesting only for windows'
+ * users) do not send their stamp in SYN. It is easy case.
+ * We simply do not advertise TS support.
+ */
+ tp.saw_tstamp = 0;
+ tp.tstamp_ok = 0;
+ }
+ tp.tstamp_ok = tp.saw_tstamp;
+
+ tcp_openreq_init(req, &tp, skb);
+
+ req->af.v4_req.loc_addr = daddr;
+ req->af.v4_req.rmt_addr = saddr;
+ req->af.v4_req.opt = tcp_v4_save_options(sk, skb);
+ req->class = &or_ipv4;
+ if (!want_cookie)
+ TCP_ECN_create_request(req, skb->h.th);
+
+ if (want_cookie) {
+#ifdef CONFIG_SYN_COOKIES
+ syn_flood_warning(skb);
+#endif
+ isn = cookie_v4_init_sequence(sk, skb, &req->mss);
+ } else if (isn == 0) {
+ struct inet_peer *peer = NULL;
+
+ /* VJ's idea. We save last timestamp seen
+ * from the destination in peer table, when entering
+ * state TIME-WAIT, and check against it before
+ * accepting new connection request.
+ *
+ * If "isn" is not zero, this request hit alive
+ * timewait bucket, so that all the necessary checks
+ * are made in the function processing timewait state.
+ */
+ if (tp.saw_tstamp &&
+ sysctl_tcp_tw_recycle &&
+ (dst = tcp_v4_route_req(sk, req)) != NULL &&
+ (peer = rt_get_peer((struct rtable*)dst)) != NULL &&
+ peer->v4daddr == saddr) {
+ if (xtime.tv_sec < peer->tcp_ts_stamp + TCP_PAWS_MSL &&
+ (s32)(peer->tcp_ts - req->ts_recent) > TCP_PAWS_WINDOW) {
+ NET_INC_STATS_BH(PAWSPassiveRejected);
+ dst_release(dst);
+ goto drop_and_free;
+ }
+ }
+ /* Kill the following clause, if you dislike this way. */
+ else if (!sysctl_tcp_syncookies &&
+ (sysctl_max_syn_backlog - tcp_synq_len(sk)
+ < (sysctl_max_syn_backlog>>2)) &&
+ (!peer || !peer->tcp_ts_stamp) &&
+ (!dst || !dst->rtt)) {
+ /* Without syncookies last quarter of
+ * backlog is filled with destinations, proven to be alive.
+ * It means that we continue to communicate
+ * to destinations, already remembered
+ * to the moment of synflood.
+ */
+ NETDEBUG(if (net_ratelimit()) \
+ printk(KERN_DEBUG "TCP: drop open request from %u.%u.%u.%u/%u\n", \
+ NIPQUAD(saddr), ntohs(skb->h.th->source)));
+ dst_release(dst);
+ goto drop_and_free;
+ }
+
+ isn = tcp_v4_init_sequence(sk, skb);
+ }
+ req->snt_isn = isn;
+
+ if (tcp_v4_send_synack(sk, req, dst))
+ goto drop_and_free;
+
+ if (want_cookie) {
+ tcp_openreq_free(req);
+ } else {
+ tcp_v4_synq_add(sk, req);
+ }
+ return 0;
+
+drop_and_free:
+ tcp_openreq_free(req);
+drop:
+ TCP_INC_STATS_BH(TcpAttemptFails);
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+
+/*
+ * The three way handshake has completed - we got a valid synack -
+ * now create the new socket.
+ */
+struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
+ struct open_request *req,
+ struct dst_entry *dst)
+{
+#if 0
+ struct tcp_opt *newtp;
+ struct sock *newsk;
+
+ if (tcp_acceptq_is_full(sk))
+ goto exit_overflow;
+
+ if (dst == NULL &&
+ (dst = tcp_v4_route_req(sk, req)) == NULL)
+ goto exit;
+
+ newsk = tcp_create_openreq_child(sk, req, skb);
+ if (!newsk)
+ goto exit;
+
+ newsk->dst_cache = dst;
+ newsk->route_caps = dst->dev->features;
+
+ newtp = &(newsk->tp_pinfo.af_tcp);
+ newsk->daddr = req->af.v4_req.rmt_addr;
+ newsk->saddr = req->af.v4_req.loc_addr;
+ newsk->rcv_saddr = req->af.v4_req.loc_addr;
+ newsk->protinfo.af_inet.opt = req->af.v4_req.opt;
+ req->af.v4_req.opt = NULL;
+ newsk->protinfo.af_inet.mc_index = tcp_v4_iif(skb);
+ newsk->protinfo.af_inet.mc_ttl = skb->nh.iph->ttl;
+ newtp->ext_header_len = 0;
+ if (newsk->protinfo.af_inet.opt)
+ newtp->ext_header_len = newsk->protinfo.af_inet.opt->optlen;
+ newsk->protinfo.af_inet.id = newtp->write_seq^jiffies;
+
+ tcp_sync_mss(newsk, dst->pmtu);
+ newtp->advmss = dst->advmss;
+ tcp_initialize_rcv_mss(newsk);
+
+ __tcp_v4_hash(newsk, 0);
+ __tcp_inherit_port(sk, newsk);
+
+ return newsk;
+
+exit_overflow:
+ NET_INC_STATS_BH(ListenOverflows);
+exit:
+ NET_INC_STATS_BH(ListenDrops);
+ dst_release(dst);
+ return NULL;
+#else
+ return NULL;
+#endif
+}
+
+static struct sock *tcp_v4_hnd_req(struct sock *sk,struct sk_buff *skb)
+{
+#if 0
+ struct open_request *req, **prev;
+ struct tcphdr *th = skb->h.th;
+ struct iphdr *iph = skb->nh.iph;
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sock *nsk;
+
+ /* Find possible connection requests. */
+ req = tcp_v4_search_req(tp, &prev,
+ th->source,
+ iph->saddr, iph->daddr);
+ if (req)
+ return tcp_check_req(sk, skb, req, prev);
+
+ nsk = __tcp_v4_lookup_established(skb->nh.iph->saddr,
+ th->source,
+ skb->nh.iph->daddr,
+ ntohs(th->dest),
+ tcp_v4_iif(skb));
+
+ if (nsk) {
+ if (nsk->state != TCP_TIME_WAIT) {
+ bh_lock_sock(nsk);
+ return nsk;
+ }
+ tcp_tw_put((struct tcp_tw_bucket*)nsk);
+ return NULL;
+ }
+
+#ifdef CONFIG_SYN_COOKIES
+ if (!th->rst && !th->syn && th->ack)
+ sk = cookie_v4_check(sk, skb, &(IPCB(skb)->opt));
+#endif
+ return sk;
+#else
+ return NULL;
+#endif
+}
+
+static int tcp_v4_checksum_init(struct sk_buff *skb)
+{
+#if 0
+ if (skb->ip_summed == CHECKSUM_HW) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ if (!tcp_v4_check(skb->h.th,skb->len,skb->nh.iph->saddr,
+ skb->nh.iph->daddr,skb->csum))
+ return 0;
+
+ NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "hw tcp v4 csum failed\n"));
+ skb->ip_summed = CHECKSUM_NONE;
+ }
+ if (skb->len <= 76) {
+ if (tcp_v4_check(skb->h.th,skb->len,skb->nh.iph->saddr,
+ skb->nh.iph->daddr,
+ skb_checksum(skb, 0, skb->len, 0)))
+ return -1;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ } else {
+ skb->csum = ~tcp_v4_check(skb->h.th,skb->len,skb->nh.iph->saddr,
+ skb->nh.iph->daddr,0);
+ }
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+
+/* The socket must have it's spinlock held when we get
+ * here.
+ *
+ * We have a potential double-lock case here, so even when
+ * doing backlog processing we use the BH locking scheme.
+ * This is because we cannot sleep with the original spinlock
+ * held.
+ */
+int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+#ifdef CONFIG_FILTER
+ struct sk_filter *filter = sk->filter;
+ if (filter && sk_filter(skb, filter))
+ goto discard;
+#endif /* CONFIG_FILTER */
+
+ IP_INC_STATS_BH(IpInDelivers);
+
+ if (sk->state == TCP_ESTABLISHED) { /* Fast path */
+ TCP_CHECK_TIMER(sk);
+ if (tcp_rcv_established(sk, skb, skb->h.th, skb->len))
+ goto reset;
+ TCP_CHECK_TIMER(sk);
+ return 0;
+ }
+
+ if (skb->len < (skb->h.th->doff<<2) || tcp_checksum_complete(skb))
+ goto csum_err;
+
+ if (sk->state == TCP_LISTEN) {
+ struct sock *nsk = tcp_v4_hnd_req(sk, skb);
+ if (!nsk)
+ goto discard;
+
+ if (nsk != sk) {
+ if (tcp_child_process(sk, nsk, skb))
+ goto reset;
+ return 0;
+ }
+ }
+
+ TCP_CHECK_TIMER(sk);
+ if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len))
+ goto reset;
+ TCP_CHECK_TIMER(sk);
+ return 0;
+
+reset:
+ tcp_v4_send_reset(skb);
+discard:
+ kfree_skb(skb);
+ /* Be careful here. If this function gets more complicated and
+ * gcc suffers from register pressure on the x86, sk (in %ebx)
+ * might be destroyed here. This current version compiles correctly,
+ * but you have been warned.
+ */
+ return 0;
+
+csum_err:
+ TCP_INC_STATS_BH(TcpInErrs);
+ goto discard;
+#else
+ return 0;
+#endif
+}
+
+/*
+ * From tcp_input.c
+ */
+
+int tcp_v4_rcv(struct sk_buff *skb)
+{
+#if 0
+ struct tcphdr *th;
+ struct sock *sk;
+ int ret;
+
+ if (skb->pkt_type!=PACKET_HOST)
+ goto discard_it;
+
+ /* Count it even if it's bad */
+ TCP_INC_STATS_BH(TcpInSegs);
+
+ if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
+ goto discard_it;
+
+ th = skb->h.th;
+
+ if (th->doff < sizeof(struct tcphdr)/4)
+ goto bad_packet;
+ if (!pskb_may_pull(skb, th->doff*4))
+ goto discard_it;
+
+ /* An explanation is required here, I think.
+ * Packet length and doff are validated by header prediction,
+ * provided case of th->doff==0 is elimineted.
+ * So, we defer the checks. */
+ if ((skb->ip_summed != CHECKSUM_UNNECESSARY &&
+ tcp_v4_checksum_init(skb) < 0))
+ goto bad_packet;
+
+ th = skb->h.th;
+ TCP_SKB_CB(skb)->seq = ntohl(th->seq);
+ TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
+ skb->len - th->doff*4);
+ TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
+ TCP_SKB_CB(skb)->when = 0;
+ TCP_SKB_CB(skb)->flags = skb->nh.iph->tos;
+ TCP_SKB_CB(skb)->sacked = 0;
+
+ sk = __tcp_v4_lookup(skb->nh.iph->saddr, th->source,
+ skb->nh.iph->daddr, ntohs(th->dest), tcp_v4_iif(skb));
+
+ if (!sk)
+ goto no_tcp_socket;
+
+process:
+ if(!ipsec_sk_policy(sk,skb))
+ goto discard_and_relse;
+
+ if (sk->state == TCP_TIME_WAIT)
+ goto do_time_wait;
+
+ skb->dev = NULL;
+
+ bh_lock_sock(sk);
+ ret = 0;
+ if (!sk->lock.users) {
+ if (!tcp_prequeue(sk, skb))
+ ret = tcp_v4_do_rcv(sk, skb);
+ } else
+ sk_add_backlog(sk, skb);
+ bh_unlock_sock(sk);
+
+ sock_put(sk);
+
+ return ret;
+
+no_tcp_socket:
+ if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
+bad_packet:
+ TCP_INC_STATS_BH(TcpInErrs);
+ } else {
+ tcp_v4_send_reset(skb);
+ }
+
+discard_it:
+ /* Discard frame. */
+ kfree_skb(skb);
+ return 0;
+
+discard_and_relse:
+ sock_put(sk);
+ goto discard_it;
+
+do_time_wait:
+ if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
+ TCP_INC_STATS_BH(TcpInErrs);
+ goto discard_and_relse;
+ }
+ switch(tcp_timewait_state_process((struct tcp_tw_bucket *)sk,
+ skb, th, skb->len)) {
+ case TCP_TW_SYN:
+ {
+ struct sock *sk2;
+
+ sk2 = tcp_v4_lookup_listener(skb->nh.iph->daddr, ntohs(th->dest), tcp_v4_iif(skb));
+ if (sk2 != NULL) {
+ tcp_tw_deschedule((struct tcp_tw_bucket *)sk);
+ tcp_timewait_kill((struct tcp_tw_bucket *)sk);
+ tcp_tw_put((struct tcp_tw_bucket *)sk);
+ sk = sk2;
+ goto process;
+ }
+ /* Fall through to ACK */
+ }
+ case TCP_TW_ACK:
+ tcp_v4_timewait_ack(sk, skb);
+ break;
+ case TCP_TW_RST:
+ goto no_tcp_socket;
+ case TCP_TW_SUCCESS:;
+ }
+ goto discard_it;
+#endif
+}
+
+/* With per-bucket locks this operation is not-atomic, so that
+ * this version is not worse.
+ */
+static void __tcp_v4_rehash(struct sock *sk)
+{
+#if 0
+ sk->prot->unhash(sk);
+ sk->prot->hash(sk);
+#endif
+}
+
+static int tcp_v4_reselect_saddr(struct sock *sk)
+{
+#if 0
+ int err;
+ struct rtable *rt;
+ __u32 old_saddr = sk->saddr;
+ __u32 new_saddr;
+ __u32 daddr = sk->daddr;
+
+ if(sk->protinfo.af_inet.opt && sk->protinfo.af_inet.opt->srr)
+ daddr = sk->protinfo.af_inet.opt->faddr;
+
+ /* Query new route. */
+ err = ip_route_connect(&rt, daddr, 0,
+ RT_TOS(sk->protinfo.af_inet.tos)|sk->localroute,
+ sk->bound_dev_if);
+ if (err)
+ return err;
+
+ __sk_dst_set(sk, &rt->u.dst);
+ sk->route_caps = rt->u.dst.dev->features;
+
+ new_saddr = rt->rt_src;
+
+ if (new_saddr == old_saddr)
+ return 0;
+
+ if (sysctl_ip_dynaddr > 1) {
+ printk(KERN_INFO "tcp_v4_rebuild_header(): shifting sk->saddr "
+ "from %d.%d.%d.%d to %d.%d.%d.%d\n",
+ NIPQUAD(old_saddr),
+ NIPQUAD(new_saddr));
+ }
+
+ sk->saddr = new_saddr;
+ sk->rcv_saddr = new_saddr;
+
+ /* XXX The only one ugly spot where we need to
+ * XXX really change the sockets identity after
+ * XXX it has entered the hashes. -DaveM
+ *
+ * Besides that, it does not check for connection
+ * uniqueness. Wait for troubles.
+ */
+ __tcp_v4_rehash(sk);
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+int tcp_v4_rebuild_header(struct sock *sk)
+{
+#if 0
+ struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0);
+ u32 daddr;
+ int err;
+
+ /* Route is OK, nothing to do. */
+ if (rt != NULL)
+ return 0;
+
+ /* Reroute. */
+ daddr = sk->daddr;
+ if(sk->protinfo.af_inet.opt && sk->protinfo.af_inet.opt->srr)
+ daddr = sk->protinfo.af_inet.opt->faddr;
+
+ err = ip_route_output(&rt, daddr, sk->saddr,
+ RT_CONN_FLAGS(sk), sk->bound_dev_if);
+ if (!err) {
+ __sk_dst_set(sk, &rt->u.dst);
+ sk->route_caps = rt->u.dst.dev->features;
+ return 0;
+ }
+
+ /* Routing failed... */
+ sk->route_caps = 0;
+
+ if (!sysctl_ip_dynaddr ||
+ sk->state != TCP_SYN_SENT ||
+ (sk->userlocks & SOCK_BINDADDR_LOCK) ||
+ (err = tcp_v4_reselect_saddr(sk)) != 0)
+ sk->err_soft=-err;
+
+ return err;
+#else
+ return 0;
+#endif
+}
+
+static void v4_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr)
+{
+#if 0
+ struct sockaddr_in *sin = (struct sockaddr_in *) uaddr;
+
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = sk->daddr;
+ sin->sin_port = sk->dport;
+#endif
+}
+
+/* VJ's idea. Save last timestamp seen from this destination
+ * and hold it at least for normal timewait interval to use for duplicate
+ * segment detection in subsequent connections, before they enter synchronized
+ * state.
+ */
+
+int tcp_v4_remember_stamp(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ struct rtable *rt = (struct rtable*)__sk_dst_get(sk);
+ struct inet_peer *peer = NULL;
+ int release_it = 0;
+
+ if (rt == NULL || rt->rt_dst != sk->daddr) {
+ peer = inet_getpeer(sk->daddr, 1);
+ release_it = 1;
+ } else {
+ if (rt->peer == NULL)
+ rt_bind_peer(rt, 1);
+ peer = rt->peer;
+ }
+
+ if (peer) {
+ if ((s32)(peer->tcp_ts - tp->ts_recent) <= 0 ||
+ (peer->tcp_ts_stamp + TCP_PAWS_MSL < xtime.tv_sec &&
+ peer->tcp_ts_stamp <= tp->ts_recent_stamp)) {
+ peer->tcp_ts_stamp = tp->ts_recent_stamp;
+ peer->tcp_ts = tp->ts_recent;
+ }
+ if (release_it)
+ inet_putpeer(peer);
+ return 1;
+ }
+
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+int tcp_v4_tw_remember_stamp(struct tcp_tw_bucket *tw)
+{
+#if 0
+ struct inet_peer *peer = NULL;
+
+ peer = inet_getpeer(tw->daddr, 1);
+
+ if (peer) {
+ if ((s32)(peer->tcp_ts - tw->ts_recent) <= 0 ||
+ (peer->tcp_ts_stamp + TCP_PAWS_MSL < xtime.tv_sec &&
+ peer->tcp_ts_stamp <= tw->ts_recent_stamp)) {
+ peer->tcp_ts_stamp = tw->ts_recent_stamp;
+ peer->tcp_ts = tw->ts_recent;
+ }
+ inet_putpeer(peer);
+ return 1;
+ }
+
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+#if 0
+struct tcp_func ipv4_specific = {
+ ip_queue_xmit,
+ tcp_v4_send_check,
+ tcp_v4_rebuild_header,
+ tcp_v4_conn_request,
+ tcp_v4_syn_recv_sock,
+ tcp_v4_remember_stamp,
+ sizeof(struct iphdr),
+
+ ip_setsockopt,
+ ip_getsockopt,
+ v4_addr2sockaddr,
+ sizeof(struct sockaddr_in)
+};
+#endif
+
+/* NOTE: A lot of things set to zero explicitly by call to
+ * sk_alloc() so need not be done here.
+ */
+static int tcp_v4_init_sock(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ skb_queue_head_init(&tp->out_of_order_queue);
+ tcp_init_xmit_timers(sk);
+ tcp_prequeue_init(tp);
+
+ tp->rto = TCP_TIMEOUT_INIT;
+ tp->mdev = TCP_TIMEOUT_INIT;
+
+ /* So many TCP implementations out there (incorrectly) count the
+ * initial SYN frame in their delayed-ACK and congestion control
+ * algorithms that we must have the following bandaid to talk
+ * efficiently to them. -DaveM
+ */
+ tp->snd_cwnd = 2;
+
+ /* See draft-stevens-tcpca-spec-01 for discussion of the
+ * initialization of these values.
+ */
+ tp->snd_ssthresh = 0x7fffffff; /* Infinity */
+ tp->snd_cwnd_clamp = ~0;
+ tp->mss_cache = 536;
+
+ tp->reordering = sysctl_tcp_reordering;
+
+ sk->state = TCP_CLOSE;
+
+ sk->write_space = tcp_write_space;
+ sk->use_write_queue = 1;
+
+ sk->tp_pinfo.af_tcp.af_specific = &ipv4_specific;
+
+ sk->sndbuf = sysctl_tcp_wmem[1];
+ sk->rcvbuf = sysctl_tcp_rmem[1];
+
+ atomic_inc(&tcp_sockets_allocated);
+
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+static int tcp_v4_destroy_sock(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ tcp_clear_xmit_timers(sk);
+
+ /* Cleanup up the write buffer. */
+ tcp_writequeue_purge(sk);
+
+ /* Cleans up our, hopefully empty, out_of_order_queue. */
+ __skb_queue_purge(&tp->out_of_order_queue);
+
+ /* Clean prequeue, it must be empty really */
+ __skb_queue_purge(&tp->ucopy.prequeue);
+
+ /* Clean up a referenced TCP bind bucket. */
+ if(sk->prev != NULL)
+ tcp_put_port(sk);
+
+ /* If sendmsg cached page exists, toss it. */
+ if (tp->sndmsg_page != NULL)
+ __free_page(tp->sndmsg_page);
+
+ atomic_dec(&tcp_sockets_allocated);
+
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+/* Proc filesystem TCP sock list dumping. */
+static void get_openreq(struct sock *sk, struct open_request *req, char *tmpbuf, int i, int uid)
+{
+#if 0
+ int ttd = req->expires - jiffies;
+
+ sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
+ " %02X %08X:%08X %02X:%08X %08X %5d %8d %u %d %p",
+ i,
+ req->af.v4_req.loc_addr,
+ ntohs(sk->sport),
+ req->af.v4_req.rmt_addr,
+ ntohs(req->rmt_port),
+ TCP_SYN_RECV,
+ 0,0, /* could print option size, but that is af dependent. */
+ 1, /* timers active (only the expire timer) */
+ ttd,
+ req->retrans,
+ uid,
+ 0, /* non standard timer */
+ 0, /* open_requests have no inode */
+ atomic_read(&sk->refcnt),
+ req
+ );
+#endif
+}
+
+static void get_tcp_sock(struct sock *sp, char *tmpbuf, int i)
+{
+#if 0
+ unsigned int dest, src;
+ __u16 destp, srcp;
+ int timer_active;
+ unsigned long timer_expires;
+ struct tcp_opt *tp = &sp->tp_pinfo.af_tcp;
+
+ dest = sp->daddr;
+ src = sp->rcv_saddr;
+ destp = ntohs(sp->dport);
+ srcp = ntohs(sp->sport);
+ if (tp->pending == TCP_TIME_RETRANS) {
+ timer_active = 1;
+ timer_expires = tp->timeout;
+ } else if (tp->pending == TCP_TIME_PROBE0) {
+ timer_active = 4;
+ timer_expires = tp->timeout;
+ } else if (timer_pending(&sp->timer)) {
+ timer_active = 2;
+ timer_expires = sp->timer.expires;
+ } else {
+ timer_active = 0;
+ timer_expires = jiffies;
+ }
+
+ sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
+ " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %u %u %u %u %d",
+ i, src, srcp, dest, destp, sp->state,
+ tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq,
+ timer_active, timer_expires-jiffies,
+ tp->retransmits,
+ sock_i_uid(sp),
+ tp->probes_out,
+ sock_i_ino(sp),
+ atomic_read(&sp->refcnt), sp,
+ tp->rto, tp->ack.ato, (tp->ack.quick<<1)|tp->ack.pingpong,
+ tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh
+ );
+#endif
+}
+
+static void get_timewait_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i)
+{
+#if 0
+ unsigned int dest, src;
+ __u16 destp, srcp;
+ int ttd = tw->ttd - jiffies;
+
+ if (ttd < 0)
+ ttd = 0;
+
+ dest = tw->daddr;
+ src = tw->rcv_saddr;
+ destp = ntohs(tw->dport);
+ srcp = ntohs(tw->sport);
+
+ sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
+ " %02X %08X:%08X %02X:%08X %08X %5d %8d %d %d %p",
+ i, src, srcp, dest, destp, tw->substate, 0, 0,
+ 3, ttd, 0, 0, 0, 0,
+ atomic_read(&tw->refcnt), tw);
+#endif
+}
+
+#define TMPSZ 150
+
+int tcp_get_info(char *buffer, char **start, off_t offset, int length)
+{
+#if 0
+ int len = 0, num = 0, i;
+ off_t begin, pos = 0;
+ char tmpbuf[TMPSZ+1];
+
+ if (offset < TMPSZ)
+ len += sprintf(buffer, "%-*s\n", TMPSZ-1,
+ " sl local_address rem_address st tx_queue "
+ "rx_queue tr tm->when retrnsmt uid timeout inode");
+
+ pos = TMPSZ;
+
+ /* First, walk listening socket table. */
+ tcp_listen_lock();
+ for(i = 0; i < TCP_LHTABLE_SIZE; i++) {
+ struct sock *sk;
+ struct tcp_listen_opt *lopt;
+ int k;
+
+ for (sk = tcp_listening_hash[i]; sk; sk = sk->next, num++) {
+ struct open_request *req;
+ int uid;
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ if (!TCP_INET_FAMILY(sk->family))
+ goto skip_listen;
+
+ pos += TMPSZ;
+ if (pos >= offset) {
+ get_tcp_sock(sk, tmpbuf, num);
+ len += sprintf(buffer+len, "%-*s\n", TMPSZ-1, tmpbuf);
+ if (pos >= offset + length) {
+ tcp_listen_unlock();
+ goto out_no_bh;
+ }
+ }
+
+skip_listen:
+ uid = sock_i_uid(sk);
+ read_lock_bh(&tp->syn_wait_lock);
+ lopt = tp->listen_opt;
+ if (lopt && lopt->qlen != 0) {
+ for (k=0; k<TCP_SYNQ_HSIZE; k++) {
+ for (req = lopt->syn_table[k]; req; req = req->dl_next, num++) {
+ if (!TCP_INET_FAMILY(req->class->family))
+ continue;
+
+ pos += TMPSZ;
+ if (pos <= offset)
+ continue;
+ get_openreq(sk, req, tmpbuf, num, uid);
+ len += sprintf(buffer+len, "%-*s\n", TMPSZ-1, tmpbuf);
+ if (pos >= offset + length) {
+ read_unlock_bh(&tp->syn_wait_lock);
+ tcp_listen_unlock();
+ goto out_no_bh;
+ }
+ }
+ }
+ }
+ read_unlock_bh(&tp->syn_wait_lock);
+
+ /* Completed requests are in normal socket hash table */
+ }
+ }
+ tcp_listen_unlock();
+
+ local_bh_disable();
+
+ /* Next, walk established hash chain. */
+ for (i = 0; i < tcp_ehash_size; i++) {
+ struct tcp_ehash_bucket *head = &tcp_ehash[i];
+ struct sock *sk;
+ struct tcp_tw_bucket *tw;
+
+ read_lock(&head->lock);
+ for(sk = head->chain; sk; sk = sk->next, num++) {
+ if (!TCP_INET_FAMILY(sk->family))
+ continue;
+ pos += TMPSZ;
+ if (pos <= offset)
+ continue;
+ get_tcp_sock(sk, tmpbuf, num);
+ len += sprintf(buffer+len, "%-*s\n", TMPSZ-1, tmpbuf);
+ if (pos >= offset + length) {
+ read_unlock(&head->lock);
+ goto out;
+ }
+ }
+ for (tw = (struct tcp_tw_bucket *)tcp_ehash[i+tcp_ehash_size].chain;
+ tw != NULL;
+ tw = (struct tcp_tw_bucket *)tw->next, num++) {
+ if (!TCP_INET_FAMILY(tw->family))
+ continue;
+ pos += TMPSZ;
+ if (pos <= offset)
+ continue;
+ get_timewait_sock(tw, tmpbuf, num);
+ len += sprintf(buffer+len, "%-*s\n", TMPSZ-1, tmpbuf);
+ if (pos >= offset + length) {
+ read_unlock(&head->lock);
+ goto out;
+ }
+ }
+ read_unlock(&head->lock);
+ }
+
+out:
+ local_bh_enable();
+out_no_bh:
+
+ begin = len - (pos - offset);
+ *start = buffer + begin;
+ len -= begin;
+ if (len > length)
+ len = length;
+ if (len < 0)
+ len = 0;
+ return len;
+#endif
+}
+
+struct proto tcp_prot = {
+ name: "TCP",
+ close: tcp_close,
+ connect: tcp_v4_connect,
+ disconnect: tcp_disconnect,
+ accept: tcp_accept,
+ ioctl: tcp_ioctl,
+ init: tcp_v4_init_sock,
+ destroy: tcp_v4_destroy_sock,
+ shutdown: tcp_shutdown,
+ setsockopt: tcp_setsockopt,
+ getsockopt: tcp_getsockopt,
+ sendmsg: tcp_sendmsg,
+ recvmsg: tcp_recvmsg,
+ backlog_rcv: tcp_v4_do_rcv,
+ hash: tcp_v4_hash,
+ unhash: tcp_unhash,
+ get_port: tcp_v4_get_port,
+};
+
+
+
+void tcp_v4_init(struct net_proto_family *ops)
+{
+#if 0
+ int err;
+
+ tcp_inode.i_mode = S_IFSOCK;
+ tcp_inode.i_sock = 1;
+ tcp_inode.i_uid = 0;
+ tcp_inode.i_gid = 0;
+ init_waitqueue_head(&tcp_inode.i_wait);
+ init_waitqueue_head(&tcp_inode.u.socket_i.wait);
+
+ tcp_socket->inode = &tcp_inode;
+ tcp_socket->state = SS_UNCONNECTED;
+ tcp_socket->type=SOCK_RAW;
+
+ if ((err=ops->create(tcp_socket, IPPROTO_TCP))<0)
+ panic("Failed to create the TCP control socket.\n");
+ tcp_socket->sk->allocation=GFP_ATOMIC;
+ tcp_socket->sk->protinfo.af_inet.ttl = MAXTTL;
+
+ /* Unhash it so that IP input processing does not even
+ * see it, we do not wish this socket to see incoming
+ * packets.
+ */
+ tcp_socket->sk->prot->unhash(tcp_socket->sk);
+#endif
+}
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS TCP/IP protocol driver
+ * FILE: transport/tcp/tcp_output.c
+ * PURPOSE: Transmission Control Protocol
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISIONS:
+ * CSH 15-01-2003 Imported from linux kernel 2.4.20
+ */
+
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Implementation of the Transmission Control Protocol(TCP).
+ *
+ * Version: $Id$
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Mark Evans, <evansmp@uhura.aston.ac.uk>
+ * Corey Minyard <wf-rch!minyard@relay.EU.net>
+ * Florian La Roche, <flla@stud.uni-sb.de>
+ * Charles Hedrick, <hedrick@klinzhai.rutgers.edu>
+ * Linus Torvalds, <torvalds@cs.helsinki.fi>
+ * Alan Cox, <gw4pts@gw4pts.ampr.org>
+ * Matthew Dillon, <dillon@apollo.west.oic.com>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Jorge Cwik, <jorge@laser.satlink.net>
+ */
+
+/*
+ * Changes: Pedro Roque : Retransmit queue handled by TCP.
+ * : Fragmentation on mtu decrease
+ * : Segment collapse on retransmit
+ * : AF independence
+ *
+ * Linus Torvalds : send_delayed_ack
+ * David S. Miller : Charge memory using the right skb
+ * during syn/ack processing.
+ * David S. Miller : Output engine completely rewritten.
+ * Andrea Arcangeli: SYNACK carry ts_recent in tsecr.
+ * Cacophonix Gaul : draft-minshall-nagle-01
+ * J Hadi Salim : ECN support
+ *
+ */
+
+#if 0
+#include <net/tcp.h>
+
+#include <linux/compiler.h>
+#include <linux/smp_lock.h>
+#else
+#include "linux.h"
+#include "tcpcore.h"
+#endif
+
+/* People can turn this off for buggy TCP's found in printers etc. */
+int sysctl_tcp_retrans_collapse = 1;
+
+static __inline__
+void update_send_head(struct sock *sk, struct tcp_opt *tp, struct sk_buff *skb)
+{
+ tp->send_head = skb->next;
+ if (tp->send_head == (struct sk_buff *) &sk->write_queue)
+ tp->send_head = NULL;
+ tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
+ if (tp->packets_out++ == 0)
+ tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+}
+
+/* SND.NXT, if window was not shrunk.
+ * If window has been shrunk, what should we make? It is not clear at all.
+ * Using SND.UNA we will fail to open window, SND.NXT is out of window. :-(
+ * Anything in between SND.UNA...SND.UNA+SND.WND also can be already
+ * invalid. OK, let's make this for now:
+ */
+static __inline__ __u32 tcp_acceptable_seq(struct sock *sk, struct tcp_opt *tp)
+{
+ if (!before(tp->snd_una+tp->snd_wnd, tp->snd_nxt))
+ return tp->snd_nxt;
+ else
+ return tp->snd_una+tp->snd_wnd;
+}
+
+/* Calculate mss to advertise in SYN segment.
+ * RFC1122, RFC1063, draft-ietf-tcpimpl-pmtud-01 state that:
+ *
+ * 1. It is independent of path mtu.
+ * 2. Ideally, it is maximal possible segment size i.e. 65535-40.
+ * 3. For IPv4 it is reasonable to calculate it from maximal MTU of
+ * attached devices, because some buggy hosts are confused by
+ * large MSS.
+ * 4. We do not make 3, we advertise MSS, calculated from first
+ * hop device mtu, but allow to raise it to ip_rt_min_advmss.
+ * This may be overriden via information stored in routing table.
+ * 5. Value 65535 for MSS is valid in IPv6 and means "as large as possible,
+ * probably even Jumbo".
+ */
+static __u16 tcp_advertise_mss(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct dst_entry *dst = __sk_dst_get(sk);
+ int mss = tp->advmss;
+
+ if (dst && dst->advmss < mss) {
+ mss = dst->advmss;
+ tp->advmss = mss;
+ }
+
+ return (__u16)mss;
+#else
+ return 0;
+#endif
+}
+
+/* RFC2861. Reset CWND after idle period longer RTO to "restart window".
+ * This is the first part of cwnd validation mechanism. */
+static void tcp_cwnd_restart(struct tcp_opt *tp)
+{
+#if 0
+ s32 delta = tcp_time_stamp - tp->lsndtime;
+ u32 restart_cwnd = tcp_init_cwnd(tp);
+ u32 cwnd = tp->snd_cwnd;
+
+ tp->snd_ssthresh = tcp_current_ssthresh(tp);
+ restart_cwnd = min(restart_cwnd, cwnd);
+
+ while ((delta -= tp->rto) > 0 && cwnd > restart_cwnd)
+ cwnd >>= 1;
+ tp->snd_cwnd = max(cwnd, restart_cwnd);
+ tp->snd_cwnd_stamp = tcp_time_stamp;
+ tp->snd_cwnd_used = 0;
+#endif
+}
+
+static __inline__ void tcp_event_data_sent(struct tcp_opt *tp, struct sk_buff *skb)
+{
+#if 0
+ u32 now = tcp_time_stamp;
+
+ if (!tp->packets_out && (s32)(now - tp->lsndtime) > tp->rto)
+ tcp_cwnd_restart(tp);
+
+ tp->lsndtime = now;
+
+ /* If it is a reply for ato after last received
+ * packet, enter pingpong mode.
+ */
+ if ((u32)(now - tp->ack.lrcvtime) < tp->ack.ato)
+ tp->ack.pingpong = 1;
+#endif
+}
+
+static __inline__ void tcp_event_ack_sent(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ tcp_dec_quickack_mode(tp);
+ tcp_clear_xmit_timer(sk, TCP_TIME_DACK);
+#endif
+}
+
+/* Chose a new window to advertise, update state in tcp_opt for the
+ * socket, and return result with RFC1323 scaling applied. The return
+ * value can be stuffed directly into th->window for an outgoing
+ * frame.
+ */
+static __inline__ u16 tcp_select_window(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ u32 cur_win = tcp_receive_window(tp);
+ u32 new_win = __tcp_select_window(sk);
+
+ /* Never shrink the offered window */
+ if(new_win < cur_win) {
+ /* Danger Will Robinson!
+ * Don't update rcv_wup/rcv_wnd here or else
+ * we will not be able to advertise a zero
+ * window in time. --DaveM
+ *
+ * Relax Will Robinson.
+ */
+ new_win = cur_win;
+ }
+ tp->rcv_wnd = new_win;
+ tp->rcv_wup = tp->rcv_nxt;
+
+ /* RFC1323 scaling applied */
+ new_win >>= tp->rcv_wscale;
+
+ /* If we advertise zero window, disable fast path. */
+ if (new_win == 0)
+ tp->pred_flags = 0;
+
+ return new_win;
+#else
+ return 0;
+#endif
+}
+
+
+/* This routine actually transmits TCP packets queued in by
+ * tcp_do_sendmsg(). This is used by both the initial
+ * transmission and possible later retransmissions.
+ * All SKB's seen here are completely headerless. It is our
+ * job to build the TCP header, and pass the packet down to
+ * IP so it can do the same plus pass the packet off to the
+ * device.
+ *
+ * We are working here with either a clone of the original
+ * SKB, or a fresh unique copy made by the retransmit engine.
+ */
+int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+ if(skb != NULL) {
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct tcp_skb_cb *tcb = TCP_SKB_CB(skb);
+ int tcp_header_size = tp->tcp_header_len;
+ struct tcphdr *th;
+ int sysctl_flags;
+ int err;
+
+#define SYSCTL_FLAG_TSTAMPS 0x1
+#define SYSCTL_FLAG_WSCALE 0x2
+#define SYSCTL_FLAG_SACK 0x4
+
+ sysctl_flags = 0;
+ if (tcb->flags & TCPCB_FLAG_SYN) {
+ tcp_header_size = sizeof(struct tcphdr) + TCPOLEN_MSS;
+ if(sysctl_tcp_timestamps) {
+ tcp_header_size += TCPOLEN_TSTAMP_ALIGNED;
+ sysctl_flags |= SYSCTL_FLAG_TSTAMPS;
+ }
+ if(sysctl_tcp_window_scaling) {
+ tcp_header_size += TCPOLEN_WSCALE_ALIGNED;
+ sysctl_flags |= SYSCTL_FLAG_WSCALE;
+ }
+ if(sysctl_tcp_sack) {
+ sysctl_flags |= SYSCTL_FLAG_SACK;
+ if(!(sysctl_flags & SYSCTL_FLAG_TSTAMPS))
+ tcp_header_size += TCPOLEN_SACKPERM_ALIGNED;
+ }
+ } else if (tp->eff_sacks) {
+ /* A SACK is 2 pad bytes, a 2 byte header, plus
+ * 2 32-bit sequence numbers for each SACK block.
+ */
+ tcp_header_size += (TCPOLEN_SACK_BASE_ALIGNED +
+ (tp->eff_sacks * TCPOLEN_SACK_PERBLOCK));
+ }
+ th = (struct tcphdr *) skb_push(skb, tcp_header_size);
+ skb->h.th = th;
+ skb_set_owner_w(skb, sk);
+
+ /* Build TCP header and checksum it. */
+ th->source = sk->sport;
+ th->dest = sk->dport;
+ th->seq = htonl(tcb->seq);
+ th->ack_seq = htonl(tp->rcv_nxt);
+ *(((__u16 *)th) + 6) = htons(((tcp_header_size >> 2) << 12) | tcb->flags);
+ if (tcb->flags & TCPCB_FLAG_SYN) {
+ /* RFC1323: The window in SYN & SYN/ACK segments
+ * is never scaled.
+ */
+ th->window = htons(tp->rcv_wnd);
+ } else {
+ th->window = htons(tcp_select_window(sk));
+ }
+ th->check = 0;
+ th->urg_ptr = 0;
+
+ if (tp->urg_mode &&
+ between(tp->snd_up, tcb->seq+1, tcb->seq+0xFFFF)) {
+ th->urg_ptr = htons(tp->snd_up-tcb->seq);
+ th->urg = 1;
+ }
+
+ if (tcb->flags & TCPCB_FLAG_SYN) {
+ tcp_syn_build_options((__u32 *)(th + 1),
+ tcp_advertise_mss(sk),
+ (sysctl_flags & SYSCTL_FLAG_TSTAMPS),
+ (sysctl_flags & SYSCTL_FLAG_SACK),
+ (sysctl_flags & SYSCTL_FLAG_WSCALE),
+ tp->rcv_wscale,
+ tcb->when,
+ tp->ts_recent);
+ } else {
+ tcp_build_and_update_options((__u32 *)(th + 1),
+ tp, tcb->when);
+
+ TCP_ECN_send(sk, tp, skb, tcp_header_size);
+ }
+ tp->af_specific->send_check(sk, th, skb->len, skb);
+
+ if (tcb->flags & TCPCB_FLAG_ACK)
+ tcp_event_ack_sent(sk);
+
+ if (skb->len != tcp_header_size)
+ tcp_event_data_sent(tp, skb);
+
+ TCP_INC_STATS(TcpOutSegs);
+
+ err = tp->af_specific->queue_xmit(skb);
+ if (err <= 0)
+ return err;
+
+ tcp_enter_cwr(tp);
+
+ /* NET_XMIT_CN is special. It does not guarantee,
+ * that this packet is lost. It tells that device
+ * is about to start to drop packets or already
+ * drops some packets of the same priority and
+ * invokes us to send less aggressively.
+ */
+ return err == NET_XMIT_CN ? 0 : err;
+ }
+ return -ENOBUFS;
+#undef SYSCTL_FLAG_TSTAMPS
+#undef SYSCTL_FLAG_WSCALE
+#undef SYSCTL_FLAG_SACK
+#else
+ return 0;
+#endif
+}
+
+
+/* This is the main buffer sending routine. We queue the buffer
+ * and decide whether to queue or transmit now.
+ *
+ * NOTE: probe0 timer is not checked, do not forget tcp_push_pending_frames,
+ * otherwise socket can stall.
+ */
+void tcp_send_skb(struct sock *sk, struct sk_buff *skb, int force_queue, unsigned cur_mss)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ /* Advance write_seq and place onto the write_queue. */
+ tp->write_seq = TCP_SKB_CB(skb)->end_seq;
+ __skb_queue_tail(&sk->write_queue, skb);
+ tcp_charge_skb(sk, skb);
+
+ if (!force_queue && tp->send_head == NULL && tcp_snd_test(tp, skb, cur_mss, tp->nonagle)) {
+ /* Send it out now. */
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ if (tcp_transmit_skb(sk, skb_clone(skb, sk->allocation)) == 0) {
+ tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
+ tcp_minshall_update(tp, cur_mss, skb);
+ if (tp->packets_out++ == 0)
+ tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+ return;
+ }
+ }
+ /* Queue it, remembering where we must start sending. */
+ if (tp->send_head == NULL)
+ tp->send_head = skb;
+#endif
+}
+
+/* Send _single_ skb sitting at the send head. This function requires
+ * true push pending frames to setup probe timer etc.
+ */
+void tcp_push_one(struct sock *sk, unsigned cur_mss)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *skb = tp->send_head;
+
+ if (tcp_snd_test(tp, skb, cur_mss, 1)) {
+ /* Send it out now. */
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ if (tcp_transmit_skb(sk, skb_clone(skb, sk->allocation)) == 0) {
+ tp->send_head = NULL;
+ tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
+ if (tp->packets_out++ == 0)
+ tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+ return;
+ }
+ }
+#endif
+}
+
+/* Split fragmented skb to two parts at length len. */
+
+static void skb_split(struct sk_buff *skb, struct sk_buff *skb1, u32 len)
+{
+#if 0
+ int i;
+ int pos = skb->len - skb->data_len;
+
+ if (len < pos) {
+ /* Split line is inside header. */
+ memcpy(skb_put(skb1, pos-len), skb->data + len, pos-len);
+
+ /* And move data appendix as is. */
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
+ skb_shinfo(skb1)->frags[i] = skb_shinfo(skb)->frags[i];
+
+ skb_shinfo(skb1)->nr_frags = skb_shinfo(skb)->nr_frags;
+ skb_shinfo(skb)->nr_frags = 0;
+
+ skb1->data_len = skb->data_len;
+ skb1->len += skb1->data_len;
+ skb->data_len = 0;
+ skb->len = len;
+ skb->tail = skb->data+len;
+ } else {
+ int k = 0;
+ int nfrags = skb_shinfo(skb)->nr_frags;
+
+ /* Second chunk has no header, nothing to copy. */
+
+ skb_shinfo(skb)->nr_frags = 0;
+ skb1->len = skb1->data_len = skb->len - len;
+ skb->len = len;
+ skb->data_len = len - pos;
+
+ for (i=0; i<nfrags; i++) {
+ int size = skb_shinfo(skb)->frags[i].size;
+ if (pos + size > len) {
+ skb_shinfo(skb1)->frags[k] = skb_shinfo(skb)->frags[i];
+
+ if (pos < len) {
+ /* Split frag.
+ * We have to variants in this case:
+ * 1. Move all the frag to the second
+ * part, if it is possible. F.e.
+ * this approach is mandatory for TUX,
+ * where splitting is expensive.
+ * 2. Split is accurately. We make this.
+ */
+ get_page(skb_shinfo(skb)->frags[i].page);
+ skb_shinfo(skb1)->frags[0].page_offset += (len-pos);
+ skb_shinfo(skb1)->frags[0].size -= (len-pos);
+ skb_shinfo(skb)->frags[i].size = len-pos;
+ skb_shinfo(skb)->nr_frags++;
+ }
+ k++;
+ } else {
+ skb_shinfo(skb)->nr_frags++;
+ }
+ pos += size;
+ }
+ skb_shinfo(skb1)->nr_frags = k;
+ }
+#endif
+}
+
+/* Function to create two new TCP segments. Shrinks the given segment
+ * to the specified size and appends a new segment with the rest of the
+ * packet to the list. This won't be called frequently, I hope.
+ * Remember, these are still headerless SKBs at this point.
+ */
+static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ struct sk_buff *buff;
+ int nsize = skb->len - len;
+ u16 flags;
+
+ if (skb_cloned(skb) &&
+ skb_is_nonlinear(skb) &&
+ pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+ return -ENOMEM;
+
+ /* Get a new skb... force flag on. */
+ buff = tcp_alloc_skb(sk, nsize, GFP_ATOMIC);
+ if (buff == NULL)
+ return -ENOMEM; /* We'll just try again later. */
+ tcp_charge_skb(sk, buff);
+
+ /* Correct the sequence numbers. */
+ TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len;
+ TCP_SKB_CB(buff)->end_seq = TCP_SKB_CB(skb)->end_seq;
+ TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(buff)->seq;
+
+ /* PSH and FIN should only be set in the second packet. */
+ flags = TCP_SKB_CB(skb)->flags;
+ TCP_SKB_CB(skb)->flags = flags & ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH);
+ TCP_SKB_CB(buff)->flags = flags;
+ TCP_SKB_CB(buff)->sacked = TCP_SKB_CB(skb)->sacked&(TCPCB_LOST|TCPCB_EVER_RETRANS|TCPCB_AT_TAIL);
+ if (TCP_SKB_CB(buff)->sacked&TCPCB_LOST) {
+ tp->lost_out++;
+ tp->left_out++;
+ }
+ TCP_SKB_CB(skb)->sacked &= ~TCPCB_AT_TAIL;
+
+ if (!skb_shinfo(skb)->nr_frags && skb->ip_summed != CHECKSUM_HW) {
+ /* Copy and checksum data tail into the new buffer. */
+ buff->csum = csum_partial_copy_nocheck(skb->data + len, skb_put(buff, nsize),
+ nsize, 0);
+
+ skb_trim(skb, len);
+
+ skb->csum = csum_block_sub(skb->csum, buff->csum, len);
+ } else {
+ skb->ip_summed = CHECKSUM_HW;
+ skb_split(skb, buff, len);
+ }
+
+ buff->ip_summed = skb->ip_summed;
+
+ /* Looks stupid, but our code really uses when of
+ * skbs, which it never sent before. --ANK
+ */
+ TCP_SKB_CB(buff)->when = TCP_SKB_CB(skb)->when;
+
+ /* Link BUFF into the send queue. */
+ __skb_append(skb, buff);
+
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+/* This function synchronize snd mss to current pmtu/exthdr set.
+
+ tp->user_mss is mss set by user by TCP_MAXSEG. It does NOT counts
+ for TCP options, but includes only bare TCP header.
+
+ tp->mss_clamp is mss negotiated at connection setup.
+ It is minumum of user_mss and mss received with SYN.
+ It also does not include TCP options.
+
+ tp->pmtu_cookie is last pmtu, seen by this function.
+
+ tp->mss_cache is current effective sending mss, including
+ all tcp options except for SACKs. It is evaluated,
+ taking into account current pmtu, but never exceeds
+ tp->mss_clamp.
+
+ NOTE1. rfc1122 clearly states that advertised MSS
+ DOES NOT include either tcp or ip options.
+
+ NOTE2. tp->pmtu_cookie and tp->mss_cache are READ ONLY outside
+ this function. --ANK (980731)
+ */
+
+int tcp_sync_mss(struct sock *sk, u32 pmtu)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ int mss_now;
+
+ /* Calculate base mss without TCP options:
+ It is MMS_S - sizeof(tcphdr) of rfc1122
+ */
+
+ mss_now = pmtu - tp->af_specific->net_header_len - sizeof(struct tcphdr);
+
+ /* Clamp it (mss_clamp does not include tcp options) */
+ if (mss_now > tp->mss_clamp)
+ mss_now = tp->mss_clamp;
+
+ /* Now subtract optional transport overhead */
+ mss_now -= tp->ext_header_len;
+
+ /* Then reserve room for full set of TCP options and 8 bytes of data */
+ if (mss_now < 48)
+ mss_now = 48;
+
+ /* Now subtract TCP options size, not including SACKs */
+ mss_now -= tp->tcp_header_len - sizeof(struct tcphdr);
+
+ /* Bound mss with half of window */
+ if (tp->max_window && mss_now > (tp->max_window>>1))
+ mss_now = max((tp->max_window>>1), 68U - tp->tcp_header_len);
+
+ /* And store cached results */
+ tp->pmtu_cookie = pmtu;
+ tp->mss_cache = mss_now;
+ return mss_now;
+#else
+ return 0;
+#endif
+}
+
+
+/* This routine writes packets to the network. It advances the
+ * send_head. This happens as incoming acks open up the remote
+ * window for us.
+ *
+ * Returns 1, if no segments are in flight and we have queued segments, but
+ * cannot send anything now because of SWS or another problem.
+ */
+int tcp_write_xmit(struct sock *sk, int nonagle)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ unsigned int mss_now;
+
+ /* If we are closed, the bytes will have to remain here.
+ * In time closedown will finish, we empty the write queue and all
+ * will be happy.
+ */
+ if(sk->state != TCP_CLOSE) {
+ struct sk_buff *skb;
+ int sent_pkts = 0;
+
+ /* Account for SACKS, we may need to fragment due to this.
+ * It is just like the real MSS changing on us midstream.
+ * We also handle things correctly when the user adds some
+ * IP options mid-stream. Silly to do, but cover it.
+ */
+ mss_now = tcp_current_mss(sk);
+
+ while((skb = tp->send_head) &&
+ tcp_snd_test(tp, skb, mss_now, tcp_skb_is_last(sk, skb) ? nonagle : 1)) {
+ if (skb->len > mss_now) {
+ if (tcp_fragment(sk, skb, mss_now))
+ break;
+ }
+
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ if (tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)))
+ break;
+ /* Advance the send_head. This one is sent out. */
+ update_send_head(sk, tp, skb);
+ tcp_minshall_update(tp, mss_now, skb);
+ sent_pkts = 1;
+ }
+
+ if (sent_pkts) {
+ tcp_cwnd_validate(sk, tp);
+ return 0;
+ }
+
+ return !tp->packets_out && tp->send_head;
+ }
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+/* This function returns the amount that we can raise the
+ * usable window based on the following constraints
+ *
+ * 1. The window can never be shrunk once it is offered (RFC 793)
+ * 2. We limit memory per socket
+ *
+ * RFC 1122:
+ * "the suggested [SWS] avoidance algorithm for the receiver is to keep
+ * RECV.NEXT + RCV.WIN fixed until:
+ * RCV.BUFF - RCV.USER - RCV.WINDOW >= min(1/2 RCV.BUFF, MSS)"
+ *
+ * i.e. don't raise the right edge of the window until you can raise
+ * it at least MSS bytes.
+ *
+ * Unfortunately, the recommended algorithm breaks header prediction,
+ * since header prediction assumes th->window stays fixed.
+ *
+ * Strictly speaking, keeping th->window fixed violates the receiver
+ * side SWS prevention criteria. The problem is that under this rule
+ * a stream of single byte packets will cause the right side of the
+ * window to always advance by a single byte.
+ *
+ * Of course, if the sender implements sender side SWS prevention
+ * then this will not be a problem.
+ *
+ * BSD seems to make the following compromise:
+ *
+ * If the free space is less than the 1/4 of the maximum
+ * space available and the free space is less than 1/2 mss,
+ * then set the window to 0.
+ * [ Actually, bsd uses MSS and 1/4 of maximal _window_ ]
+ * Otherwise, just prevent the window from shrinking
+ * and from being larger than the largest representable value.
+ *
+ * This prevents incremental opening of the window in the regime
+ * where TCP is limited by the speed of the reader side taking
+ * data out of the TCP receive queue. It does nothing about
+ * those cases where the window is constrained on the sender side
+ * because the pipeline is full.
+ *
+ * BSD also seems to "accidentally" limit itself to windows that are a
+ * multiple of MSS, at least until the free space gets quite small.
+ * This would appear to be a side effect of the mbuf implementation.
+ * Combining these two algorithms results in the observed behavior
+ * of having a fixed window size at almost all times.
+ *
+ * Below we obtain similar behavior by forcing the offered window to
+ * a multiple of the mss when it is feasible to do so.
+ *
+ * Note, we don't "adjust" for TIMESTAMP or SACK option bytes.
+ * Regular options like TIMESTAMP are taken into account.
+ */
+u32 __tcp_select_window(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ /* MSS for the peer's data. Previous verions used mss_clamp
+ * here. I don't know if the value based on our guesses
+ * of peer's MSS is better for the performance. It's more correct
+ * but may be worse for the performance because of rcv_mss
+ * fluctuations. --SAW 1998/11/1
+ */
+ int mss = tp->ack.rcv_mss;
+ int free_space = tcp_space(sk);
+ int full_space = min_t(int, tp->window_clamp, tcp_full_space(sk));
+ int window;
+
+ if (mss > full_space)
+ mss = full_space;
+
+ if (free_space < full_space/2) {
+ tp->ack.quick = 0;
+
+ if (tcp_memory_pressure)
+ tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U*tp->advmss);
+
+ if (free_space < mss)
+ return 0;
+ }
+
+ if (free_space > tp->rcv_ssthresh)
+ free_space = tp->rcv_ssthresh;
+
+ /* Get the largest window that is a nice multiple of mss.
+ * Window clamp already applied above.
+ * If our current window offering is within 1 mss of the
+ * free space we just keep it. This prevents the divide
+ * and multiply from happening most of the time.
+ * We also don't do any window rounding when the free space
+ * is too small.
+ */
+ window = tp->rcv_wnd;
+ if (window <= free_space - mss || window > free_space)
+ window = (free_space/mss)*mss;
+
+ return window;
+#else
+ return 0;
+#endif
+}
+
+/* Attempt to collapse two adjacent SKB's during retransmission. */
+static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int mss_now)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ struct sk_buff *next_skb = skb->next;
+
+ /* The first test we must make is that neither of these two
+ * SKB's are still referenced by someone else.
+ */
+ if(!skb_cloned(skb) && !skb_cloned(next_skb)) {
+ int skb_size = skb->len, next_skb_size = next_skb->len;
+ u16 flags = TCP_SKB_CB(skb)->flags;
+
+ /* Also punt if next skb has been SACK'd. */
+ if(TCP_SKB_CB(next_skb)->sacked & TCPCB_SACKED_ACKED)
+ return;
+
+ /* Next skb is out of window. */
+ if (after(TCP_SKB_CB(next_skb)->end_seq, tp->snd_una+tp->snd_wnd))
+ return;
+
+ /* Punt if not enough space exists in the first SKB for
+ * the data in the second, or the total combined payload
+ * would exceed the MSS.
+ */
+ if ((next_skb_size > skb_tailroom(skb)) ||
+ ((skb_size + next_skb_size) > mss_now))
+ return;
+
+ /* Ok. We will be able to collapse the packet. */
+ __skb_unlink(next_skb, next_skb->list);
+
+ if (next_skb->ip_summed == CHECKSUM_HW)
+ skb->ip_summed = CHECKSUM_HW;
+
+ if (skb->ip_summed != CHECKSUM_HW) {
+ memcpy(skb_put(skb, next_skb_size), next_skb->data, next_skb_size);
+ skb->csum = csum_block_add(skb->csum, next_skb->csum, skb_size);
+ }
+
+ /* Update sequence range on original skb. */
+ TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(next_skb)->end_seq;
+
+ /* Merge over control information. */
+ flags |= TCP_SKB_CB(next_skb)->flags; /* This moves PSH/FIN etc. over */
+ TCP_SKB_CB(skb)->flags = flags;
+
+ /* All done, get rid of second SKB and account for it so
+ * packet counting does not break.
+ */
+ TCP_SKB_CB(skb)->sacked |= TCP_SKB_CB(next_skb)->sacked&(TCPCB_EVER_RETRANS|TCPCB_AT_TAIL);
+ if (TCP_SKB_CB(next_skb)->sacked&TCPCB_SACKED_RETRANS)
+ tp->retrans_out--;
+ if (TCP_SKB_CB(next_skb)->sacked&TCPCB_LOST) {
+ tp->lost_out--;
+ tp->left_out--;
+ }
+ /* Reno case is special. Sigh... */
+ if (!tp->sack_ok && tp->sacked_out) {
+ tp->sacked_out--;
+ tp->left_out--;
+ }
+
+ /* Not quite right: it can be > snd.fack, but
+ * it is better to underestimate fackets.
+ */
+ if (tp->fackets_out)
+ tp->fackets_out--;
+ tcp_free_skb(sk, next_skb);
+ tp->packets_out--;
+ }
+#endif
+}
+
+/* Do a simple retransmit without using the backoff mechanisms in
+ * tcp_timer. This is used for path mtu discovery.
+ * The socket is already locked here.
+ */
+void tcp_simple_retransmit(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *skb;
+ unsigned int mss = tcp_current_mss(sk);
+ int lost = 0;
+
+ for_retrans_queue(skb, sk, tp) {
+ if (skb->len > mss &&
+ !(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED)) {
+ if (TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_RETRANS) {
+ TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
+ tp->retrans_out--;
+ }
+ if (!(TCP_SKB_CB(skb)->sacked&TCPCB_LOST)) {
+ TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
+ tp->lost_out++;
+ lost = 1;
+ }
+ }
+ }
+
+ if (!lost)
+ return;
+
+ tcp_sync_left_out(tp);
+
+ /* Don't muck with the congestion window here.
+ * Reason is that we do not increase amount of _data_
+ * in network, but units changed and effective
+ * cwnd/ssthresh really reduced now.
+ */
+ if (tp->ca_state != TCP_CA_Loss) {
+ tp->high_seq = tp->snd_nxt;
+ tp->snd_ssthresh = tcp_current_ssthresh(tp);
+ tp->prior_ssthresh = 0;
+ tp->undo_marker = 0;
+ tp->ca_state = TCP_CA_Loss;
+ }
+ tcp_xmit_retransmit_queue(sk);
+#endif
+}
+
+/* This retransmits one SKB. Policy decisions and retransmit queue
+ * state updates are done by the caller. Returns non-zero if an
+ * error occurred which prevented the send.
+ */
+int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ unsigned int cur_mss = tcp_current_mss(sk);
+ int err;
+
+ /* Do not sent more than we queued. 1/4 is reserved for possible
+ * copying overhead: frgagmentation, tunneling, mangling etc.
+ */
+ if (atomic_read(&sk->wmem_alloc) > min(sk->wmem_queued+(sk->wmem_queued>>2),sk->sndbuf))
+ return -EAGAIN;
+
+ /* If receiver has shrunk his window, and skb is out of
+ * new window, do not retransmit it. The exception is the
+ * case, when window is shrunk to zero. In this case
+ * our retransmit serves as a zero window probe.
+ */
+ if (!before(TCP_SKB_CB(skb)->seq, tp->snd_una+tp->snd_wnd)
+ && TCP_SKB_CB(skb)->seq != tp->snd_una)
+ return -EAGAIN;
+
+ if(skb->len > cur_mss) {
+ if(tcp_fragment(sk, skb, cur_mss))
+ return -ENOMEM; /* We'll try again later. */
+
+ /* New SKB created, account for it. */
+ tp->packets_out++;
+ }
+
+ /* Collapse two adjacent packets if worthwhile and we can. */
+ if(!(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_SYN) &&
+ (skb->len < (cur_mss >> 1)) &&
+ (skb->next != tp->send_head) &&
+ (skb->next != (struct sk_buff *)&sk->write_queue) &&
+ (skb_shinfo(skb)->nr_frags == 0 && skb_shinfo(skb->next)->nr_frags == 0) &&
+ (sysctl_tcp_retrans_collapse != 0))
+ tcp_retrans_try_collapse(sk, skb, cur_mss);
+
+ if(tp->af_specific->rebuild_header(sk))
+ return -EHOSTUNREACH; /* Routing failure or similar. */
+
+ /* Some Solaris stacks overoptimize and ignore the FIN on a
+ * retransmit when old data is attached. So strip it off
+ * since it is cheap to do so and saves bytes on the network.
+ */
+ if(skb->len > 0 &&
+ (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
+ tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) {
+ if (!pskb_trim(skb, 0)) {
+ TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1;
+ skb->ip_summed = CHECKSUM_NONE;
+ skb->csum = 0;
+ }
+ }
+
+ /* Make a copy, if the first transmission SKB clone we made
+ * is still in somebody's hands, else make a clone.
+ */
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+
+ err = tcp_transmit_skb(sk, (skb_cloned(skb) ?
+ pskb_copy(skb, GFP_ATOMIC):
+ skb_clone(skb, GFP_ATOMIC)));
+
+ if (err == 0) {
+ /* Update global TCP statistics. */
+ TCP_INC_STATS(TcpRetransSegs);
+
+#if FASTRETRANS_DEBUG > 0
+ if (TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_RETRANS) {
+ if (net_ratelimit())
+ printk(KERN_DEBUG "retrans_out leaked.\n");
+ }
+#endif
+ TCP_SKB_CB(skb)->sacked |= TCPCB_RETRANS;
+ tp->retrans_out++;
+
+ /* Save stamp of the first retransmit. */
+ if (!tp->retrans_stamp)
+ tp->retrans_stamp = TCP_SKB_CB(skb)->when;
+
+ tp->undo_retrans++;
+
+ /* snd_nxt is stored to detect loss of retransmitted segment,
+ * see tcp_input.c tcp_sacktag_write_queue().
+ */
+ TCP_SKB_CB(skb)->ack_seq = tp->snd_nxt;
+ }
+ return err;
+#else
+ return 0;
+#endif
+}
+
+/* This gets called after a retransmit timeout, and the initially
+ * retransmitted data is acknowledged. It tries to continue
+ * resending the rest of the retransmit queue, until either
+ * we've sent it all or the congestion window limit is reached.
+ * If doing SACK, the first ACK which comes back for a timeout
+ * based retransmit packet might feed us FACK information again.
+ * If so, we use it to avoid unnecessarily retransmissions.
+ */
+void tcp_xmit_retransmit_queue(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *skb;
+ int packet_cnt = tp->lost_out;
+
+ /* First pass: retransmit lost packets. */
+ if (packet_cnt) {
+ for_retrans_queue(skb, sk, tp) {
+ __u8 sacked = TCP_SKB_CB(skb)->sacked;
+
+ if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)
+ return;
+
+ if (sacked&TCPCB_LOST) {
+ if (!(sacked&(TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS))) {
+ if (tcp_retransmit_skb(sk, skb))
+ return;
+ if (tp->ca_state != TCP_CA_Loss)
+ NET_INC_STATS_BH(TCPFastRetrans);
+ else
+ NET_INC_STATS_BH(TCPSlowStartRetrans);
+
+ if (skb == skb_peek(&sk->write_queue))
+ tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+ }
+
+ if (--packet_cnt <= 0)
+ break;
+ }
+ }
+ }
+
+ /* OK, demanded retransmission is finished. */
+
+ /* Forward retransmissions are possible only during Recovery. */
+ if (tp->ca_state != TCP_CA_Recovery)
+ return;
+
+ /* No forward retransmissions in Reno are possible. */
+ if (!tp->sack_ok)
+ return;
+
+ /* Yeah, we have to make difficult choice between forward transmission
+ * and retransmission... Both ways have their merits...
+ *
+ * For now we do not retrnamsit anything, while we have some new
+ * segments to send.
+ */
+
+ if (tcp_may_send_now(sk, tp))
+ return;
+
+ packet_cnt = 0;
+
+ for_retrans_queue(skb, sk, tp) {
+ if(++packet_cnt > tp->fackets_out)
+ break;
+
+ if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)
+ break;
+
+ if(TCP_SKB_CB(skb)->sacked & TCPCB_TAGBITS)
+ continue;
+
+ /* Ok, retransmit it. */
+ if(tcp_retransmit_skb(sk, skb))
+ break;
+
+ if (skb == skb_peek(&sk->write_queue))
+ tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+
+ NET_INC_STATS_BH(TCPForwardRetrans);
+ }
+#endif
+}
+
+
+/* Send a fin. The caller locks the socket for us. This cannot be
+ * allowed to fail queueing a FIN frame under any circumstances.
+ */
+void tcp_send_fin(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *skb = skb_peek_tail(&sk->write_queue);
+ unsigned int mss_now;
+
+ /* Optimization, tack on the FIN if we have a queue of
+ * unsent frames. But be careful about outgoing SACKS
+ * and IP options.
+ */
+ mss_now = tcp_current_mss(sk);
+
+ if(tp->send_head != NULL) {
+ TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_FIN;
+ TCP_SKB_CB(skb)->end_seq++;
+ tp->write_seq++;
+ } else {
+ /* Socket is locked, keep trying until memory is available. */
+ for (;;) {
+ skb = alloc_skb(MAX_TCP_HEADER, GFP_KERNEL);
+ if (skb)
+ break;
+ yield();
+ }
+
+ /* Reserve space for headers and prepare control bits. */
+ skb_reserve(skb, MAX_TCP_HEADER);
+ skb->csum = 0;
+ TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_FIN);
+ TCP_SKB_CB(skb)->sacked = 0;
+
+ /* FIN eats a sequence byte, write_seq advanced by tcp_send_skb(). */
+ TCP_SKB_CB(skb)->seq = tp->write_seq;
+ TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
+ tcp_send_skb(sk, skb, 1, mss_now);
+ }
+ __tcp_push_pending_frames(sk, tp, mss_now, 1);
+#endif
+}
+
+/* We get here when a process closes a file descriptor (either due to
+ * an explicit close() or as a byproduct of exit()'ing) and there
+ * was unread data in the receive queue. This behavior is recommended
+ * by draft-ietf-tcpimpl-prob-03.txt section 3.10. -DaveM
+ */
+void tcp_send_active_reset(struct sock *sk, int priority)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *skb;
+
+ /* NOTE: No TCP options attached and we never retransmit this. */
+ skb = alloc_skb(MAX_TCP_HEADER, priority);
+ if (!skb) {
+ NET_INC_STATS(TCPAbortFailed);
+ return;
+ }
+
+ /* Reserve space for headers and prepare control bits. */
+ skb_reserve(skb, MAX_TCP_HEADER);
+ skb->csum = 0;
+ TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_RST);
+ TCP_SKB_CB(skb)->sacked = 0;
+
+ /* Send it off. */
+ TCP_SKB_CB(skb)->seq = tcp_acceptable_seq(sk, tp);
+ TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq;
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ if (tcp_transmit_skb(sk, skb))
+ NET_INC_STATS(TCPAbortFailed);
+#endif
+}
+
+/* WARNING: This routine must only be called when we have already sent
+ * a SYN packet that crossed the incoming SYN that caused this routine
+ * to get called. If this assumption fails then the initial rcv_wnd
+ * and rcv_wscale values will not be correct.
+ */
+int tcp_send_synack(struct sock *sk)
+{
+#if 0
+ struct sk_buff* skb;
+
+ skb = skb_peek(&sk->write_queue);
+ if (skb == NULL || !(TCP_SKB_CB(skb)->flags&TCPCB_FLAG_SYN)) {
+ printk(KERN_DEBUG "tcp_send_synack: wrong queue state\n");
+ return -EFAULT;
+ }
+ if (!(TCP_SKB_CB(skb)->flags&TCPCB_FLAG_ACK)) {
+ if (skb_cloned(skb)) {
+ struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC);
+ if (nskb == NULL)
+ return -ENOMEM;
+ __skb_unlink(skb, &sk->write_queue);
+ __skb_queue_head(&sk->write_queue, nskb);
+ tcp_free_skb(sk, skb);
+ tcp_charge_skb(sk, nskb);
+ skb = nskb;
+ }
+
+ TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_ACK;
+ TCP_ECN_send_synack(&sk->tp_pinfo.af_tcp, skb);
+ }
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ return tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC));
+#else
+ return 0;
+#endif
+}
+
+/*
+ * Prepare a SYN-ACK.
+ */
+struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
+ struct open_request *req)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct tcphdr *th;
+ int tcp_header_size;
+ struct sk_buff *skb;
+
+ skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15, 1, GFP_ATOMIC);
+ if (skb == NULL)
+ return NULL;
+
+ /* Reserve space for headers. */
+ skb_reserve(skb, MAX_TCP_HEADER);
+
+ skb->dst = dst_clone(dst);
+
+ tcp_header_size = (sizeof(struct tcphdr) + TCPOLEN_MSS +
+ (req->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0) +
+ (req->wscale_ok ? TCPOLEN_WSCALE_ALIGNED : 0) +
+ /* SACK_PERM is in the place of NOP NOP of TS */
+ ((req->sack_ok && !req->tstamp_ok) ? TCPOLEN_SACKPERM_ALIGNED : 0));
+ skb->h.th = th = (struct tcphdr *) skb_push(skb, tcp_header_size);
+
+ memset(th, 0, sizeof(struct tcphdr));
+ th->syn = 1;
+ th->ack = 1;
+ TCP_ECN_make_synack(req, th);
+ th->source = sk->sport;
+ th->dest = req->rmt_port;
+ TCP_SKB_CB(skb)->seq = req->snt_isn;
+ TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
+ th->seq = htonl(TCP_SKB_CB(skb)->seq);
+ th->ack_seq = htonl(req->rcv_isn + 1);
+ if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */
+ __u8 rcv_wscale;
+ /* Set this up on the first call only */
+ req->window_clamp = tp->window_clamp ? : dst->window;
+ /* tcp_full_space because it is guaranteed to be the first packet */
+ tcp_select_initial_window(tcp_full_space(sk),
+ dst->advmss - (req->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0),
+ &req->rcv_wnd,
+ &req->window_clamp,
+ req->wscale_ok,
+ &rcv_wscale);
+ req->rcv_wscale = rcv_wscale;
+ }
+
+ /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */
+ th->window = htons(req->rcv_wnd);
+
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ tcp_syn_build_options((__u32 *)(th + 1), dst->advmss, req->tstamp_ok,
+ req->sack_ok, req->wscale_ok, req->rcv_wscale,
+ TCP_SKB_CB(skb)->when,
+ req->ts_recent);
+
+ skb->csum = 0;
+ th->doff = (tcp_header_size >> 2);
+ TCP_INC_STATS(TcpOutSegs);
+ return skb;
+#else
+ return 0;
+#endif
+}
+
+/*
+ * Do all connect socket setups that can be done AF independent.
+ */
+static inline void tcp_connect_init(struct sock *sk)
+{
+#if 0
+ struct dst_entry *dst = __sk_dst_get(sk);
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ /* We'll fix this up when we get a response from the other end.
+ * See tcp_input.c:tcp_rcv_state_process case TCP_SYN_SENT.
+ */
+ tp->tcp_header_len = sizeof(struct tcphdr) +
+ (sysctl_tcp_timestamps ? TCPOLEN_TSTAMP_ALIGNED : 0);
+
+ /* If user gave his TCP_MAXSEG, record it to clamp */
+ if (tp->user_mss)
+ tp->mss_clamp = tp->user_mss;
+ tp->max_window = 0;
+ tcp_sync_mss(sk, dst->pmtu);
+
+ if (!tp->window_clamp)
+ tp->window_clamp = dst->window;
+ tp->advmss = dst->advmss;
+ tcp_initialize_rcv_mss(sk);
+
+ tcp_select_initial_window(tcp_full_space(sk),
+ tp->advmss - (tp->ts_recent_stamp ? tp->tcp_header_len - sizeof(struct tcphdr) : 0),
+ &tp->rcv_wnd,
+ &tp->window_clamp,
+ sysctl_tcp_window_scaling,
+ &tp->rcv_wscale);
+
+ tp->rcv_ssthresh = tp->rcv_wnd;
+
+ sk->err = 0;
+ sk->done = 0;
+ tp->snd_wnd = 0;
+ tcp_init_wl(tp, tp->write_seq, 0);
+ tp->snd_una = tp->write_seq;
+ tp->snd_sml = tp->write_seq;
+ tp->rcv_nxt = 0;
+ tp->rcv_wup = 0;
+ tp->copied_seq = 0;
+
+ tp->rto = TCP_TIMEOUT_INIT;
+ tp->retransmits = 0;
+ tcp_clear_retrans(tp);
+#endif
+}
+
+/*
+ * Build a SYN and send it off.
+ */
+int tcp_connect(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *buff;
+
+ tcp_connect_init(sk);
+
+ buff = alloc_skb(MAX_TCP_HEADER + 15, sk->allocation);
+ if (unlikely(buff == NULL))
+ return -ENOBUFS;
+
+ /* Reserve space for headers. */
+ skb_reserve(buff, MAX_TCP_HEADER);
+
+ TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN;
+ TCP_ECN_send_syn(tp, buff);
+ TCP_SKB_CB(buff)->sacked = 0;
+ buff->csum = 0;
+ TCP_SKB_CB(buff)->seq = tp->write_seq++;
+ TCP_SKB_CB(buff)->end_seq = tp->write_seq;
+ tp->snd_nxt = tp->write_seq;
+ tp->pushed_seq = tp->write_seq;
+
+ /* Send it off. */
+ TCP_SKB_CB(buff)->when = tcp_time_stamp;
+ tp->retrans_stamp = TCP_SKB_CB(buff)->when;
+ __skb_queue_tail(&sk->write_queue, buff);
+ tcp_charge_skb(sk, buff);
+ tp->packets_out++;
+ tcp_transmit_skb(sk, skb_clone(buff, GFP_KERNEL));
+ TCP_INC_STATS(TcpActiveOpens);
+
+ /* Timer for repeating the SYN until an answer. */
+ tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+/* Send out a delayed ack, the caller does the policy checking
+ * to see if we should even be here. See tcp_input.c:tcp_ack_snd_check()
+ * for details.
+ */
+void tcp_send_delayed_ack(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ int ato = tp->ack.ato;
+ unsigned long timeout;
+
+ if (ato > TCP_DELACK_MIN) {
+ int max_ato = HZ/2;
+
+ if (tp->ack.pingpong || (tp->ack.pending&TCP_ACK_PUSHED))
+ max_ato = TCP_DELACK_MAX;
+
+ /* Slow path, intersegment interval is "high". */
+
+ /* If some rtt estimate is known, use it to bound delayed ack.
+ * Do not use tp->rto here, use results of rtt measurements
+ * directly.
+ */
+ if (tp->srtt) {
+ int rtt = max(tp->srtt>>3, TCP_DELACK_MIN);
+
+ if (rtt < max_ato)
+ max_ato = rtt;
+ }
+
+ ato = min(ato, max_ato);
+ }
+
+ /* Stay within the limit we were given */
+ timeout = jiffies + ato;
+
+ /* Use new timeout only if there wasn't a older one earlier. */
+ if (tp->ack.pending&TCP_ACK_TIMER) {
+ /* If delack timer was blocked or is about to expire,
+ * send ACK now.
+ */
+ if (tp->ack.blocked || time_before_eq(tp->ack.timeout, jiffies+(ato>>2))) {
+ tcp_send_ack(sk);
+ return;
+ }
+
+ if (!time_before(timeout, tp->ack.timeout))
+ timeout = tp->ack.timeout;
+ }
+ tp->ack.pending |= TCP_ACK_SCHED|TCP_ACK_TIMER;
+ tp->ack.timeout = timeout;
+ if (!mod_timer(&tp->delack_timer, timeout))
+ sock_hold(sk);
+#endif
+}
+
+/* This routine sends an ack and also updates the window. */
+void tcp_send_ack(struct sock *sk)
+{
+#if 0
+ /* If we have been reset, we may not send again. */
+ if(sk->state != TCP_CLOSE) {
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *buff;
+
+ /* We are not putting this on the write queue, so
+ * tcp_transmit_skb() will set the ownership to this
+ * sock.
+ */
+ buff = alloc_skb(MAX_TCP_HEADER, GFP_ATOMIC);
+ if (buff == NULL) {
+ tcp_schedule_ack(tp);
+ tp->ack.ato = TCP_ATO_MIN;
+ tcp_reset_xmit_timer(sk, TCP_TIME_DACK, TCP_DELACK_MAX);
+ return;
+ }
+
+ /* Reserve space for headers and prepare control bits. */
+ skb_reserve(buff, MAX_TCP_HEADER);
+ buff->csum = 0;
+ TCP_SKB_CB(buff)->flags = TCPCB_FLAG_ACK;
+ TCP_SKB_CB(buff)->sacked = 0;
+
+ /* Send it off, this clears delayed acks for us. */
+ TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tcp_acceptable_seq(sk, tp);
+ TCP_SKB_CB(buff)->when = tcp_time_stamp;
+ tcp_transmit_skb(sk, buff);
+ }
+#else
+ return 0;
+#endif
+}
+
+/* This routine sends a packet with an out of date sequence
+ * number. It assumes the other end will try to ack it.
+ *
+ * Question: what should we make while urgent mode?
+ * 4.4BSD forces sending single byte of data. We cannot send
+ * out of window data, because we have SND.NXT==SND.MAX...
+ *
+ * Current solution: to send TWO zero-length segments in urgent mode:
+ * one is with SEG.SEQ=SND.UNA to deliver urgent pointer, another is
+ * out-of-date with SND.UNA-1 to probe window.
+ */
+static int tcp_xmit_probe_skb(struct sock *sk, int urgent)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *skb;
+
+ /* We don't queue it, tcp_transmit_skb() sets ownership. */
+ skb = alloc_skb(MAX_TCP_HEADER, GFP_ATOMIC);
+ if (skb == NULL)
+ return -1;
+
+ /* Reserve space for headers and set control bits. */
+ skb_reserve(skb, MAX_TCP_HEADER);
+ skb->csum = 0;
+ TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
+ TCP_SKB_CB(skb)->sacked = urgent;
+
+ /* Use a previous sequence. This should cause the other
+ * end to send an ack. Don't queue or clone SKB, just
+ * send it.
+ */
+ TCP_SKB_CB(skb)->seq = urgent ? tp->snd_una : tp->snd_una - 1;
+ TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq;
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ return tcp_transmit_skb(sk, skb);
+#else
+ return 0;
+#endif
+}
+
+int tcp_write_wakeup(struct sock *sk)
+{
+#if 0
+ if (sk->state != TCP_CLOSE) {
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct sk_buff *skb;
+
+ if ((skb = tp->send_head) != NULL &&
+ before(TCP_SKB_CB(skb)->seq, tp->snd_una+tp->snd_wnd)) {
+ int err;
+ int mss = tcp_current_mss(sk);
+ int seg_size = tp->snd_una+tp->snd_wnd-TCP_SKB_CB(skb)->seq;
+
+ if (before(tp->pushed_seq, TCP_SKB_CB(skb)->end_seq))
+ tp->pushed_seq = TCP_SKB_CB(skb)->end_seq;
+
+ /* We are probing the opening of a window
+ * but the window size is != 0
+ * must have been a result SWS avoidance ( sender )
+ */
+ if (seg_size < TCP_SKB_CB(skb)->end_seq - TCP_SKB_CB(skb)->seq ||
+ skb->len > mss) {
+ seg_size = min(seg_size, mss);
+ TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
+ if (tcp_fragment(sk, skb, seg_size))
+ return -1;
+ }
+ TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
+ TCP_SKB_CB(skb)->when = tcp_time_stamp;
+ err = tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC));
+ if (!err) {
+ update_send_head(sk, tp, skb);
+ }
+ return err;
+ } else {
+ if (tp->urg_mode &&
+ between(tp->snd_up, tp->snd_una+1, tp->snd_una+0xFFFF))
+ tcp_xmit_probe_skb(sk, TCPCB_URG);
+ return tcp_xmit_probe_skb(sk, 0);
+ }
+ }
+ return -1;
+#else
+ return 0;
+#endif
+}
+
+/* A window probe timeout has occurred. If window is not closed send
+ * a partial packet else a zero probe.
+ */
+void tcp_send_probe0(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int err;
+
+ err = tcp_write_wakeup(sk);
+
+ if (tp->packets_out || !tp->send_head) {
+ /* Cancel probe timer, if it is not required. */
+ tp->probes_out = 0;
+ tp->backoff = 0;
+ return;
+ }
+
+ if (err <= 0) {
+ tp->backoff++;
+ tp->probes_out++;
+ tcp_reset_xmit_timer (sk, TCP_TIME_PROBE0,
+ min(tp->rto << tp->backoff, TCP_RTO_MAX));
+ } else {
+ /* If packet was not sent due to local congestion,
+ * do not backoff and do not remember probes_out.
+ * Let local senders to fight for local resources.
+ *
+ * Use accumulated backoff yet.
+ */
+ if (!tp->probes_out)
+ tp->probes_out=1;
+ tcp_reset_xmit_timer (sk, TCP_TIME_PROBE0,
+ min(tp->rto << tp->backoff, TCP_RESOURCE_PROBE_INTERVAL));
+ }
+#endif
+}
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS TCP/IP protocol driver
+ * FILE: transport/tcp/tcp_input.c
+ * PURPOSE: Transmission Control Protocol
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISIONS:
+ * CSH 15-01-2003 Imported from linux kernel 2.4.20
+ */
+
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Implementation of the Transmission Control Protocol(TCP).
+ *
+ * Version: $Id$
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Mark Evans, <evansmp@uhura.aston.ac.uk>
+ * Corey Minyard <wf-rch!minyard@relay.EU.net>
+ * Florian La Roche, <flla@stud.uni-sb.de>
+ * Charles Hedrick, <hedrick@klinzhai.rutgers.edu>
+ * Linus Torvalds, <torvalds@cs.helsinki.fi>
+ * Alan Cox, <gw4pts@gw4pts.ampr.org>
+ * Matthew Dillon, <dillon@apollo.west.oic.com>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Jorge Cwik, <jorge@laser.satlink.net>
+ */
+
+#if 0
+#include <net/tcp.h>
+#else
+#include "linux.h"
+#include "tcpcore.h"
+#endif
+
+int sysctl_tcp_syn_retries = TCP_SYN_RETRIES;
+int sysctl_tcp_synack_retries = TCP_SYNACK_RETRIES;
+//int sysctl_tcp_keepalive_time = TCP_KEEPALIVE_TIME;
+int sysctl_tcp_keepalive_probes = TCP_KEEPALIVE_PROBES;
+//int sysctl_tcp_keepalive_intvl = TCP_KEEPALIVE_INTVL;
+int sysctl_tcp_retries1 = TCP_RETR1;
+int sysctl_tcp_retries2 = TCP_RETR2;
+int sysctl_tcp_orphan_retries;
+
+static void tcp_write_timer(unsigned long);
+static void tcp_delack_timer(unsigned long);
+static void tcp_keepalive_timer (unsigned long data);
+
+//const char timer_bug_msg[] = KERN_DEBUG "tcpbug: unknown timer value\n";
+
+/*
+ * Using different timers for retransmit, delayed acks and probes
+ * We may wish use just one timer maintaining a list of expire jiffies
+ * to optimize.
+ */
+
+void tcp_init_xmit_timers(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ init_timer(&tp->retransmit_timer);
+ tp->retransmit_timer.function=&tcp_write_timer;
+ tp->retransmit_timer.data = (unsigned long) sk;
+ tp->pending = 0;
+
+ init_timer(&tp->delack_timer);
+ tp->delack_timer.function=&tcp_delack_timer;
+ tp->delack_timer.data = (unsigned long) sk;
+ tp->ack.pending = 0;
+
+ init_timer(&sk->timer);
+ sk->timer.function=&tcp_keepalive_timer;
+ sk->timer.data = (unsigned long) sk;
+#endif
+}
+
+void tcp_clear_xmit_timers(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ tp->pending = 0;
+ if (timer_pending(&tp->retransmit_timer) &&
+ del_timer(&tp->retransmit_timer))
+ __sock_put(sk);
+
+ tp->ack.pending = 0;
+ tp->ack.blocked = 0;
+ if (timer_pending(&tp->delack_timer) &&
+ del_timer(&tp->delack_timer))
+ __sock_put(sk);
+
+ if(timer_pending(&sk->timer) && del_timer(&sk->timer))
+ __sock_put(sk);
+#endif
+}
+
+static void tcp_write_err(struct sock *sk)
+{
+#if 0
+ sk->err = sk->err_soft ? : ETIMEDOUT;
+ sk->error_report(sk);
+
+ tcp_done(sk);
+ NET_INC_STATS_BH(TCPAbortOnTimeout);
+#endif
+}
+
+/* Do not allow orphaned sockets to eat all our resources.
+ * This is direct violation of TCP specs, but it is required
+ * to prevent DoS attacks. It is called when a retransmission timeout
+ * or zero probe timeout occurs on orphaned socket.
+ *
+ * Criterium is still not confirmed experimentally and may change.
+ * We kill the socket, if:
+ * 1. If number of orphaned sockets exceeds an administratively configured
+ * limit.
+ * 2. If we have strong memory pressure.
+ */
+static int tcp_out_of_resources(struct sock *sk, int do_reset)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int orphans = atomic_read(&tcp_orphan_count);
+
+ /* If peer does not open window for long time, or did not transmit
+ * anything for long time, penalize it. */
+ if ((s32)(tcp_time_stamp - tp->lsndtime) > 2*TCP_RTO_MAX || !do_reset)
+ orphans <<= 1;
+
+ /* If some dubious ICMP arrived, penalize even more. */
+ if (sk->err_soft)
+ orphans <<= 1;
+
+ if (orphans >= sysctl_tcp_max_orphans ||
+ (sk->wmem_queued > SOCK_MIN_SNDBUF &&
+ atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])) {
+ if (net_ratelimit())
+ printk(KERN_INFO "Out of socket memory\n");
+
+ /* Catch exceptional cases, when connection requires reset.
+ * 1. Last segment was sent recently. */
+ if ((s32)(tcp_time_stamp - tp->lsndtime) <= TCP_TIMEWAIT_LEN ||
+ /* 2. Window is closed. */
+ (!tp->snd_wnd && !tp->packets_out))
+ do_reset = 1;
+ if (do_reset)
+ tcp_send_active_reset(sk, GFP_ATOMIC);
+ tcp_done(sk);
+ NET_INC_STATS_BH(TCPAbortOnMemory);
+ return 1;
+ }
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+/* Calculate maximal number or retries on an orphaned socket. */
+static int tcp_orphan_retries(struct sock *sk, int alive)
+{
+#if 0
+ int retries = sysctl_tcp_orphan_retries; /* May be zero. */
+
+ /* We know from an ICMP that something is wrong. */
+ if (sk->err_soft && !alive)
+ retries = 0;
+
+ /* However, if socket sent something recently, select some safe
+ * number of retries. 8 corresponds to >100 seconds with minimal
+ * RTO of 200msec. */
+ if (retries == 0 && alive)
+ retries = 8;
+ return retries;
+#else
+ return 0;
+#endif
+}
+
+/* A write timeout has occurred. Process the after effects. */
+static int tcp_write_timeout(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int retry_until;
+
+ if ((1<<sk->state)&(TCPF_SYN_SENT|TCPF_SYN_RECV)) {
+ if (tp->retransmits)
+ dst_negative_advice(&sk->dst_cache);
+ retry_until = tp->syn_retries ? : sysctl_tcp_syn_retries;
+ } else {
+ if (tp->retransmits >= sysctl_tcp_retries1) {
+ /* NOTE. draft-ietf-tcpimpl-pmtud-01.txt requires pmtu black
+ hole detection. :-(
+
+ It is place to make it. It is not made. I do not want
+ to make it. It is disguisting. It does not work in any
+ case. Let me to cite the same draft, which requires for
+ us to implement this:
+
+ "The one security concern raised by this memo is that ICMP black holes
+ are often caused by over-zealous security administrators who block
+ all ICMP messages. It is vitally important that those who design and
+ deploy security systems understand the impact of strict filtering on
+ upper-layer protocols. The safest web site in the world is worthless
+ if most TCP implementations cannot transfer data from it. It would
+ be far nicer to have all of the black holes fixed rather than fixing
+ all of the TCP implementations."
+
+ Golden words :-).
+ */
+
+ dst_negative_advice(&sk->dst_cache);
+ }
+
+ retry_until = sysctl_tcp_retries2;
+ if (sk->dead) {
+ int alive = (tp->rto < TCP_RTO_MAX);
+
+ retry_until = tcp_orphan_retries(sk, alive);
+
+ if (tcp_out_of_resources(sk, alive || tp->retransmits < retry_until))
+ return 1;
+ }
+ }
+
+ if (tp->retransmits >= retry_until) {
+ /* Has it gone just too far? */
+ tcp_write_err(sk);
+ return 1;
+ }
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+static void tcp_delack_timer(unsigned long data)
+{
+#if 0
+ struct sock *sk = (struct sock*)data;
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ bh_lock_sock(sk);
+ if (sk->lock.users) {
+ /* Try again later. */
+ tp->ack.blocked = 1;
+ NET_INC_STATS_BH(DelayedACKLocked);
+ if (!mod_timer(&tp->delack_timer, jiffies + TCP_DELACK_MIN))
+ sock_hold(sk);
+ goto out_unlock;
+ }
+
+ tcp_mem_reclaim(sk);
+
+ if (sk->state == TCP_CLOSE || !(tp->ack.pending&TCP_ACK_TIMER))
+ goto out;
+
+ if ((long)(tp->ack.timeout - jiffies) > 0) {
+ if (!mod_timer(&tp->delack_timer, tp->ack.timeout))
+ sock_hold(sk);
+ goto out;
+ }
+ tp->ack.pending &= ~TCP_ACK_TIMER;
+
+ if (skb_queue_len(&tp->ucopy.prequeue)) {
+ struct sk_buff *skb;
+
+ net_statistics[smp_processor_id()*2].TCPSchedulerFailed += skb_queue_len(&tp->ucopy.prequeue);
+
+ while ((skb = __skb_dequeue(&tp->ucopy.prequeue)) != NULL)
+ sk->backlog_rcv(sk, skb);
+
+ tp->ucopy.memory = 0;
+ }
+
+ if (tcp_ack_scheduled(tp)) {
+ if (!tp->ack.pingpong) {
+ /* Delayed ACK missed: inflate ATO. */
+ tp->ack.ato = min(tp->ack.ato << 1, tp->rto);
+ } else {
+ /* Delayed ACK missed: leave pingpong mode and
+ * deflate ATO.
+ */
+ tp->ack.pingpong = 0;
+ tp->ack.ato = TCP_ATO_MIN;
+ }
+ tcp_send_ack(sk);
+ NET_INC_STATS_BH(DelayedACKs);
+ }
+ TCP_CHECK_TIMER(sk);
+
+out:
+ if (tcp_memory_pressure)
+ tcp_mem_reclaim(sk);
+out_unlock:
+ bh_unlock_sock(sk);
+ sock_put(sk);
+#endif
+}
+
+static void tcp_probe_timer(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ int max_probes;
+
+ if (tp->packets_out || !tp->send_head) {
+ tp->probes_out = 0;
+ return;
+ }
+
+ /* *WARNING* RFC 1122 forbids this
+ *
+ * It doesn't AFAIK, because we kill the retransmit timer -AK
+ *
+ * FIXME: We ought not to do it, Solaris 2.5 actually has fixing
+ * this behaviour in Solaris down as a bug fix. [AC]
+ *
+ * Let me to explain. probes_out is zeroed by incoming ACKs
+ * even if they advertise zero window. Hence, connection is killed only
+ * if we received no ACKs for normal connection timeout. It is not killed
+ * only because window stays zero for some time, window may be zero
+ * until armageddon and even later. We are in full accordance
+ * with RFCs, only probe timer combines both retransmission timeout
+ * and probe timeout in one bottle. --ANK
+ */
+ max_probes = sysctl_tcp_retries2;
+
+ if (sk->dead) {
+ int alive = ((tp->rto<<tp->backoff) < TCP_RTO_MAX);
+
+ max_probes = tcp_orphan_retries(sk, alive);
+
+ if (tcp_out_of_resources(sk, alive || tp->probes_out <= max_probes))
+ return;
+ }
+
+ if (tp->probes_out > max_probes) {
+ tcp_write_err(sk);
+ } else {
+ /* Only send another probe if we didn't close things up. */
+ tcp_send_probe0(sk);
+ }
+#endif
+}
+
+/*
+ * The TCP retransmit timer.
+ */
+
+static void tcp_retransmit_timer(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+
+ if (tp->packets_out == 0)
+ goto out;
+
+ BUG_TRAP(!skb_queue_empty(&sk->write_queue));
+
+ if (tp->snd_wnd == 0 && !sk->dead &&
+ !((1<<sk->state)&(TCPF_SYN_SENT|TCPF_SYN_RECV))) {
+ /* Receiver dastardly shrinks window. Our retransmits
+ * become zero probes, but we should not timeout this
+ * connection. If the socket is an orphan, time it out,
+ * we cannot allow such beasts to hang infinitely.
+ */
+#ifdef TCP_DEBUG
+ if (net_ratelimit())
+ printk(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n",
+ NIPQUAD(sk->daddr), htons(sk->dport), sk->num,
+ tp->snd_una, tp->snd_nxt);
+#endif
+ if (tcp_time_stamp - tp->rcv_tstamp > TCP_RTO_MAX) {
+ tcp_write_err(sk);
+ goto out;
+ }
+ tcp_enter_loss(sk, 0);
+ tcp_retransmit_skb(sk, skb_peek(&sk->write_queue));
+ __sk_dst_reset(sk);
+ goto out_reset_timer;
+ }
+
+ if (tcp_write_timeout(sk))
+ goto out;
+
+ if (tp->retransmits == 0) {
+ if (tp->ca_state == TCP_CA_Disorder || tp->ca_state == TCP_CA_Recovery) {
+ if (tp->sack_ok) {
+ if (tp->ca_state == TCP_CA_Recovery)
+ NET_INC_STATS_BH(TCPSackRecoveryFail);
+ else
+ NET_INC_STATS_BH(TCPSackFailures);
+ } else {
+ if (tp->ca_state == TCP_CA_Recovery)
+ NET_INC_STATS_BH(TCPRenoRecoveryFail);
+ else
+ NET_INC_STATS_BH(TCPRenoFailures);
+ }
+ } else if (tp->ca_state == TCP_CA_Loss) {
+ NET_INC_STATS_BH(TCPLossFailures);
+ } else {
+ NET_INC_STATS_BH(TCPTimeouts);
+ }
+ }
+
+ tcp_enter_loss(sk, 0);
+
+ if (tcp_retransmit_skb(sk, skb_peek(&sk->write_queue)) > 0) {
+ /* Retransmission failed because of local congestion,
+ * do not backoff.
+ */
+ if (!tp->retransmits)
+ tp->retransmits=1;
+ tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS,
+ min(tp->rto, TCP_RESOURCE_PROBE_INTERVAL));
+ goto out;
+ }
+
+ /* Increase the timeout each time we retransmit. Note that
+ * we do not increase the rtt estimate. rto is initialized
+ * from rtt, but increases here. Jacobson (SIGCOMM 88) suggests
+ * that doubling rto each time is the least we can get away with.
+ * In KA9Q, Karn uses this for the first few times, and then
+ * goes to quadratic. netBSD doubles, but only goes up to *64,
+ * and clamps at 1 to 64 sec afterwards. Note that 120 sec is
+ * defined in the protocol as the maximum possible RTT. I guess
+ * we'll have to use something other than TCP to talk to the
+ * University of Mars.
+ *
+ * PAWS allows us longer timeouts and large windows, so once
+ * implemented ftp to mars will work nicely. We will have to fix
+ * the 120 second clamps though!
+ */
+ tp->backoff++;
+ tp->retransmits++;
+
+out_reset_timer:
+ tp->rto = min(tp->rto << 1, TCP_RTO_MAX);
+ tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+ if (tp->retransmits > sysctl_tcp_retries1)
+ __sk_dst_reset(sk);
+
+out:;
+#endif
+}
+
+static void tcp_write_timer(unsigned long data)
+{
+#if 0
+ struct sock *sk = (struct sock*)data;
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ int event;
+
+ bh_lock_sock(sk);
+ if (sk->lock.users) {
+ /* Try again later */
+ if (!mod_timer(&tp->retransmit_timer, jiffies + (HZ/20)))
+ sock_hold(sk);
+ goto out_unlock;
+ }
+
+ if (sk->state == TCP_CLOSE || !tp->pending)
+ goto out;
+
+ if ((long)(tp->timeout - jiffies) > 0) {
+ if (!mod_timer(&tp->retransmit_timer, tp->timeout))
+ sock_hold(sk);
+ goto out;
+ }
+
+ event = tp->pending;
+ tp->pending = 0;
+
+ switch (event) {
+ case TCP_TIME_RETRANS:
+ tcp_retransmit_timer(sk);
+ break;
+ case TCP_TIME_PROBE0:
+ tcp_probe_timer(sk);
+ break;
+ }
+ TCP_CHECK_TIMER(sk);
+
+out:
+ tcp_mem_reclaim(sk);
+out_unlock:
+ bh_unlock_sock(sk);
+ sock_put(sk);
+#endif
+}
+
+/*
+ * Timer for listening sockets
+ */
+
+static void tcp_synack_timer(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct tcp_listen_opt *lopt = tp->listen_opt;
+ int max_retries = tp->syn_retries ? : sysctl_tcp_synack_retries;
+ int thresh = max_retries;
+ unsigned long now = jiffies;
+ struct open_request **reqp, *req;
+ int i, budget;
+
+ if (lopt == NULL || lopt->qlen == 0)
+ return;
+
+ /* Normally all the openreqs are young and become mature
+ * (i.e. converted to established socket) for first timeout.
+ * If synack was not acknowledged for 3 seconds, it means
+ * one of the following things: synack was lost, ack was lost,
+ * rtt is high or nobody planned to ack (i.e. synflood).
+ * When server is a bit loaded, queue is populated with old
+ * open requests, reducing effective size of queue.
+ * When server is well loaded, queue size reduces to zero
+ * after several minutes of work. It is not synflood,
+ * it is normal operation. The solution is pruning
+ * too old entries overriding normal timeout, when
+ * situation becomes dangerous.
+ *
+ * Essentially, we reserve half of room for young
+ * embrions; and abort old ones without pity, if old
+ * ones are about to clog our table.
+ */
+ if (lopt->qlen>>(lopt->max_qlen_log-1)) {
+ int young = (lopt->qlen_young<<1);
+
+ while (thresh > 2) {
+ if (lopt->qlen < young)
+ break;
+ thresh--;
+ young <<= 1;
+ }
+ }
+
+ if (tp->defer_accept)
+ max_retries = tp->defer_accept;
+
+ budget = 2*(TCP_SYNQ_HSIZE/(TCP_TIMEOUT_INIT/TCP_SYNQ_INTERVAL));
+ i = lopt->clock_hand;
+
+ do {
+ reqp=&lopt->syn_table[i];
+ while ((req = *reqp) != NULL) {
+ if ((long)(now - req->expires) >= 0) {
+ if ((req->retrans < thresh ||
+ (req->acked && req->retrans < max_retries))
+ && !req->class->rtx_syn_ack(sk, req, NULL)) {
+ unsigned long timeo;
+
+ if (req->retrans++ == 0)
+ lopt->qlen_young--;
+ timeo = min((TCP_TIMEOUT_INIT << req->retrans),
+ TCP_RTO_MAX);
+ req->expires = now + timeo;
+ reqp = &req->dl_next;
+ continue;
+ }
+
+ /* Drop this request */
+ write_lock(&tp->syn_wait_lock);
+ *reqp = req->dl_next;
+ write_unlock(&tp->syn_wait_lock);
+ lopt->qlen--;
+ if (req->retrans == 0)
+ lopt->qlen_young--;
+ tcp_openreq_free(req);
+ continue;
+ }
+ reqp = &req->dl_next;
+ }
+
+ i = (i+1)&(TCP_SYNQ_HSIZE-1);
+
+ } while (--budget > 0);
+
+ lopt->clock_hand = i;
+
+ if (lopt->qlen)
+ tcp_reset_keepalive_timer(sk, TCP_SYNQ_INTERVAL);
+#endif
+}
+
+void tcp_delete_keepalive_timer (struct sock *sk)
+{
+#if 0
+ if (timer_pending(&sk->timer) && del_timer (&sk->timer))
+ __sock_put(sk);
+#endif
+}
+
+void tcp_reset_keepalive_timer (struct sock *sk, unsigned long len)
+{
+#if 0
+ if (!mod_timer(&sk->timer, jiffies+len))
+ sock_hold(sk);
+#endif
+}
+
+void tcp_set_keepalive(struct sock *sk, int val)
+{
+#if 0
+ if ((1<<sk->state)&(TCPF_CLOSE|TCPF_LISTEN))
+ return;
+
+ if (val && !sk->keepopen)
+ tcp_reset_keepalive_timer(sk, keepalive_time_when(&sk->tp_pinfo.af_tcp));
+ else if (!val)
+ tcp_delete_keepalive_timer(sk);
+#endif
+}
+
+
+static void tcp_keepalive_timer (unsigned long data)
+{
+#if 0
+ struct sock *sk = (struct sock *) data;
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ __u32 elapsed;
+
+ /* Only process if socket is not in use. */
+ bh_lock_sock(sk);
+ if (sk->lock.users) {
+ /* Try again later. */
+ tcp_reset_keepalive_timer (sk, HZ/20);
+ goto out;
+ }
+
+ if (sk->state == TCP_LISTEN) {
+ tcp_synack_timer(sk);
+ goto out;
+ }
+
+ if (sk->state == TCP_FIN_WAIT2 && sk->dead) {
+ if (tp->linger2 >= 0) {
+ int tmo = tcp_fin_time(tp) - TCP_TIMEWAIT_LEN;
+
+ if (tmo > 0) {
+ tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
+ goto out;
+ }
+ }
+ tcp_send_active_reset(sk, GFP_ATOMIC);
+ goto death;
+ }
+
+ if (!sk->keepopen || sk->state == TCP_CLOSE)
+ goto out;
+
+ elapsed = keepalive_time_when(tp);
+
+ /* It is alive without keepalive 8) */
+ if (tp->packets_out || tp->send_head)
+ goto resched;
+
+ elapsed = tcp_time_stamp - tp->rcv_tstamp;
+
+ if (elapsed >= keepalive_time_when(tp)) {
+ if ((!tp->keepalive_probes && tp->probes_out >= sysctl_tcp_keepalive_probes) ||
+ (tp->keepalive_probes && tp->probes_out >= tp->keepalive_probes)) {
+ tcp_send_active_reset(sk, GFP_ATOMIC);
+ tcp_write_err(sk);
+ goto out;
+ }
+ if (tcp_write_wakeup(sk) <= 0) {
+ tp->probes_out++;
+ elapsed = keepalive_intvl_when(tp);
+ } else {
+ /* If keepalive was lost due to local congestion,
+ * try harder.
+ */
+ elapsed = TCP_RESOURCE_PROBE_INTERVAL;
+ }
+ } else {
+ /* It is tp->rcv_tstamp + keepalive_time_when(tp) */
+ elapsed = keepalive_time_when(tp) - elapsed;
+ }
+
+ TCP_CHECK_TIMER(sk);
+ tcp_mem_reclaim(sk);
+
+resched:
+ tcp_reset_keepalive_timer (sk, elapsed);
+ goto out;
+
+death:
+ tcp_done(sk);
+
+out:
+ bh_unlock_sock(sk);
+ sock_put(sk);
+#endif
+}
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS TCP/IP protocol driver
+ * FILE: transport/tcp/tcpcore.c
+ * PURPOSE: Transmission Control Protocol
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISIONS:
+ * CSH 15-01-2003 Imported from linux kernel 2.4.20
+ */
+
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Implementation of the Transmission Control Protocol(TCP).
+ *
+ * Version: $Id$
+ *
+ * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Mark Evans, <evansmp@uhura.aston.ac.uk>
+ * Corey Minyard <wf-rch!minyard@relay.EU.net>
+ * Florian La Roche, <flla@stud.uni-sb.de>
+ * Charles Hedrick, <hedrick@klinzhai.rutgers.edu>
+ * Linus Torvalds, <torvalds@cs.helsinki.fi>
+ * Alan Cox, <gw4pts@gw4pts.ampr.org>
+ * Matthew Dillon, <dillon@apollo.west.oic.com>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Jorge Cwik, <jorge@laser.satlink.net>
+ *
+ * Fixes:
+ * Alan Cox : Numerous verify_area() calls
+ * Alan Cox : Set the ACK bit on a reset
+ * Alan Cox : Stopped it crashing if it closed while
+ * sk->inuse=1 and was trying to connect
+ * (tcp_err()).
+ * Alan Cox : All icmp error handling was broken
+ * pointers passed where wrong and the
+ * socket was looked up backwards. Nobody
+ * tested any icmp error code obviously.
+ * Alan Cox : tcp_err() now handled properly. It
+ * wakes people on errors. poll
+ * behaves and the icmp error race
+ * has gone by moving it into sock.c
+ * Alan Cox : tcp_send_reset() fixed to work for
+ * everything not just packets for
+ * unknown sockets.
+ * Alan Cox : tcp option processing.
+ * Alan Cox : Reset tweaked (still not 100%) [Had
+ * syn rule wrong]
+ * Herp Rosmanith : More reset fixes
+ * Alan Cox : No longer acks invalid rst frames.
+ * Acking any kind of RST is right out.
+ * Alan Cox : Sets an ignore me flag on an rst
+ * receive otherwise odd bits of prattle
+ * escape still
+ * Alan Cox : Fixed another acking RST frame bug.
+ * Should stop LAN workplace lockups.
+ * Alan Cox : Some tidyups using the new skb list
+ * facilities
+ * Alan Cox : sk->keepopen now seems to work
+ * Alan Cox : Pulls options out correctly on accepts
+ * Alan Cox : Fixed assorted sk->rqueue->next errors
+ * Alan Cox : PSH doesn't end a TCP read. Switched a
+ * bit to skb ops.
+ * Alan Cox : Tidied tcp_data to avoid a potential
+ * nasty.
+ * Alan Cox : Added some better commenting, as the
+ * tcp is hard to follow
+ * Alan Cox : Removed incorrect check for 20 * psh
+ * Michael O'Reilly : ack < copied bug fix.
+ * Johannes Stille : Misc tcp fixes (not all in yet).
+ * Alan Cox : FIN with no memory -> CRASH
+ * Alan Cox : Added socket option proto entries.
+ * Also added awareness of them to accept.
+ * Alan Cox : Added TCP options (SOL_TCP)
+ * Alan Cox : Switched wakeup calls to callbacks,
+ * so the kernel can layer network
+ * sockets.
+ * Alan Cox : Use ip_tos/ip_ttl settings.
+ * Alan Cox : Handle FIN (more) properly (we hope).
+ * Alan Cox : RST frames sent on unsynchronised
+ * state ack error.
+ * Alan Cox : Put in missing check for SYN bit.
+ * Alan Cox : Added tcp_select_window() aka NET2E
+ * window non shrink trick.
+ * Alan Cox : Added a couple of small NET2E timer
+ * fixes
+ * Charles Hedrick : TCP fixes
+ * Toomas Tamm : TCP window fixes
+ * Alan Cox : Small URG fix to rlogin ^C ack fight
+ * Charles Hedrick : Rewrote most of it to actually work
+ * Linus : Rewrote tcp_read() and URG handling
+ * completely
+ * Gerhard Koerting: Fixed some missing timer handling
+ * Matthew Dillon : Reworked TCP machine states as per RFC
+ * Gerhard Koerting: PC/TCP workarounds
+ * Adam Caldwell : Assorted timer/timing errors
+ * Matthew Dillon : Fixed another RST bug
+ * Alan Cox : Move to kernel side addressing changes.
+ * Alan Cox : Beginning work on TCP fastpathing
+ * (not yet usable)
+ * Arnt Gulbrandsen: Turbocharged tcp_check() routine.
+ * Alan Cox : TCP fast path debugging
+ * Alan Cox : Window clamping
+ * Michael Riepe : Bug in tcp_check()
+ * Matt Dillon : More TCP improvements and RST bug fixes
+ * Matt Dillon : Yet more small nasties remove from the
+ * TCP code (Be very nice to this man if
+ * tcp finally works 100%) 8)
+ * Alan Cox : BSD accept semantics.
+ * Alan Cox : Reset on closedown bug.
+ * Peter De Schrijver : ENOTCONN check missing in tcp_sendto().
+ * Michael Pall : Handle poll() after URG properly in
+ * all cases.
+ * Michael Pall : Undo the last fix in tcp_read_urg()
+ * (multi URG PUSH broke rlogin).
+ * Michael Pall : Fix the multi URG PUSH problem in
+ * tcp_readable(), poll() after URG
+ * works now.
+ * Michael Pall : recv(...,MSG_OOB) never blocks in the
+ * BSD api.
+ * Alan Cox : Changed the semantics of sk->socket to
+ * fix a race and a signal problem with
+ * accept() and async I/O.
+ * Alan Cox : Relaxed the rules on tcp_sendto().
+ * Yury Shevchuk : Really fixed accept() blocking problem.
+ * Craig I. Hagan : Allow for BSD compatible TIME_WAIT for
+ * clients/servers which listen in on
+ * fixed ports.
+ * Alan Cox : Cleaned the above up and shrank it to
+ * a sensible code size.
+ * Alan Cox : Self connect lockup fix.
+ * Alan Cox : No connect to multicast.
+ * Ross Biro : Close unaccepted children on master
+ * socket close.
+ * Alan Cox : Reset tracing code.
+ * Alan Cox : Spurious resets on shutdown.
+ * Alan Cox : Giant 15 minute/60 second timer error
+ * Alan Cox : Small whoops in polling before an
+ * accept.
+ * Alan Cox : Kept the state trace facility since
+ * it's handy for debugging.
+ * Alan Cox : More reset handler fixes.
+ * Alan Cox : Started rewriting the code based on
+ * the RFC's for other useful protocol
+ * references see: Comer, KA9Q NOS, and
+ * for a reference on the difference
+ * between specifications and how BSD
+ * works see the 4.4lite source.
+ * A.N.Kuznetsov : Don't time wait on completion of tidy
+ * close.
+ * Linus Torvalds : Fin/Shutdown & copied_seq changes.
+ * Linus Torvalds : Fixed BSD port reuse to work first syn
+ * Alan Cox : Reimplemented timers as per the RFC
+ * and using multiple timers for sanity.
+ * Alan Cox : Small bug fixes, and a lot of new
+ * comments.
+ * Alan Cox : Fixed dual reader crash by locking
+ * the buffers (much like datagram.c)
+ * Alan Cox : Fixed stuck sockets in probe. A probe
+ * now gets fed up of retrying without
+ * (even a no space) answer.
+ * Alan Cox : Extracted closing code better
+ * Alan Cox : Fixed the closing state machine to
+ * resemble the RFC.
+ * Alan Cox : More 'per spec' fixes.
+ * Jorge Cwik : Even faster checksumming.
+ * Alan Cox : tcp_data() doesn't ack illegal PSH
+ * only frames. At least one pc tcp stack
+ * generates them.
+ * Alan Cox : Cache last socket.
+ * Alan Cox : Per route irtt.
+ * Matt Day : poll()->select() match BSD precisely on error
+ * Alan Cox : New buffers
+ * Marc Tamsky : Various sk->prot->retransmits and
+ * sk->retransmits misupdating fixed.
+ * Fixed tcp_write_timeout: stuck close,
+ * and TCP syn retries gets used now.
+ * Mark Yarvis : In tcp_read_wakeup(), don't send an
+ * ack if state is TCP_CLOSED.
+ * Alan Cox : Look up device on a retransmit - routes may
+ * change. Doesn't yet cope with MSS shrink right
+ * but its a start!
+ * Marc Tamsky : Closing in closing fixes.
+ * Mike Shaver : RFC1122 verifications.
+ * Alan Cox : rcv_saddr errors.
+ * Alan Cox : Block double connect().
+ * Alan Cox : Small hooks for enSKIP.
+ * Alexey Kuznetsov: Path MTU discovery.
+ * Alan Cox : Support soft errors.
+ * Alan Cox : Fix MTU discovery pathological case
+ * when the remote claims no mtu!
+ * Marc Tamsky : TCP_CLOSE fix.
+ * Colin (G3TNE) : Send a reset on syn ack replies in
+ * window but wrong (fixes NT lpd problems)
+ * Pedro Roque : Better TCP window handling, delayed ack.
+ * Joerg Reuter : No modification of locked buffers in
+ * tcp_do_retransmit()
+ * Eric Schenk : Changed receiver side silly window
+ * avoidance algorithm to BSD style
+ * algorithm. This doubles throughput
+ * against machines running Solaris,
+ * and seems to result in general
+ * improvement.
+ * Stefan Magdalinski : adjusted tcp_readable() to fix FIONREAD
+ * Willy Konynenberg : Transparent proxying support.
+ * Mike McLagan : Routing by source
+ * Keith Owens : Do proper merging with partial SKB's in
+ * tcp_do_sendmsg to avoid burstiness.
+ * Eric Schenk : Fix fast close down bug with
+ * shutdown() followed by close().
+ * Andi Kleen : Make poll agree with SIGIO
+ * Salvatore Sanfilippo : Support SO_LINGER with linger == 1 and
+ * lingertime == 0 (RFC 793 ABORT Call)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or(at your option) any later version.
+ *
+ * Description of States:
+ *
+ * TCP_SYN_SENT sent a connection request, waiting for ack
+ *
+ * TCP_SYN_RECV received a connection request, sent ack,
+ * waiting for final ack in three-way handshake.
+ *
+ * TCP_ESTABLISHED connection established
+ *
+ * TCP_FIN_WAIT1 our side has shutdown, waiting to complete
+ * transmission of remaining buffered data
+ *
+ * TCP_FIN_WAIT2 all buffered data sent, waiting for remote
+ * to shutdown
+ *
+ * TCP_CLOSING both sides have shutdown but we still have
+ * data we have to finish sending
+ *
+ * TCP_TIME_WAIT timeout to catch resent junk before entering
+ * closed, can only be entered from FIN_WAIT2
+ * or CLOSING. Required because the other end
+ * may not have gotten our last ACK causing it
+ * to retransmit the data packet (which we ignore)
+ *
+ * TCP_CLOSE_WAIT remote side has shutdown and is waiting for
+ * us to finish writing our data and to shutdown
+ * (we have to close() to move on to LAST_ACK)
+ *
+ * TCP_LAST_ACK out side has shutdown after remote has
+ * shutdown. There may still be data in our
+ * buffer that we have to finish sending
+ *
+ * TCP_CLOSE socket is finished
+ */
+
+#if 0
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/smp_lock.h>
+#include <linux/fs.h>
+
+#include <net/icmp.h>
+#include <net/tcp.h>
+
+#include <asm/uaccess.h>
+#include <asm/ioctls.h>
+#else
+#include "linux.h"
+#include "tcpcore.h"
+#endif
+
+int sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT;
+
+#ifdef ROS_STATISTICS
+struct tcp_mib tcp_statistics[NR_CPUS*2];
+#endif
+
+kmem_cache_t *tcp_openreq_cachep;
+kmem_cache_t *tcp_bucket_cachep;
+kmem_cache_t *tcp_timewait_cachep;
+
+#if 0
+atomic_t tcp_orphan_count = ATOMIC_INIT(0);
+#endif
+
+int sysctl_tcp_mem[3];
+int sysctl_tcp_wmem[3] = { 4*1024, 16*1024, 128*1024 };
+int sysctl_tcp_rmem[3] = { 4*1024, 87380, 87380*2 };
+
+atomic_t tcp_memory_allocated; /* Current allocated memory. */
+atomic_t tcp_sockets_allocated; /* Current number of TCP sockets. */
+
+/* Pressure flag: try to collapse.
+ * Technical note: it is used by multiple contexts non atomically.
+ * All the tcp_mem_schedule() is of this nature: accounting
+ * is strict, actions are advisory and have some latency. */
+int tcp_memory_pressure;
+
+#define TCP_PAGES(amt) (((amt)+TCP_MEM_QUANTUM-1)/TCP_MEM_QUANTUM)
+
+int tcp_mem_schedule(struct sock *sk, int size, int kind)
+{
+ int amt = TCP_PAGES(size);
+
+ sk->forward_alloc += amt*TCP_MEM_QUANTUM;
+ atomic_add(amt, &tcp_memory_allocated);
+
+ /* Under limit. */
+ if (atomic_read(&tcp_memory_allocated) < sysctl_tcp_mem[0]) {
+ if (tcp_memory_pressure)
+ tcp_memory_pressure = 0;
+ return 1;
+ }
+
+ /* Over hard limit. */
+ if (atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2]) {
+ tcp_enter_memory_pressure();
+ goto suppress_allocation;
+ }
+
+ /* Under pressure. */
+ if (atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[1])
+ tcp_enter_memory_pressure();
+
+ if (kind) {
+ if (atomic_read(&sk->rmem_alloc) < sysctl_tcp_rmem[0])
+ return 1;
+ } else {
+ if (sk->wmem_queued < sysctl_tcp_wmem[0])
+ return 1;
+ }
+
+ if (!tcp_memory_pressure ||
+ sysctl_tcp_mem[2] > atomic_read(&tcp_sockets_allocated)
+ * TCP_PAGES(sk->wmem_queued+atomic_read(&sk->rmem_alloc)+
+ sk->forward_alloc))
+ return 1;
+
+suppress_allocation:
+
+ if (kind == 0) {
+ tcp_moderate_sndbuf(sk);
+
+ /* Fail only if socket is _under_ its sndbuf.
+ * In this case we cannot block, so that we have to fail.
+ */
+ if (sk->wmem_queued+size >= sk->sndbuf)
+ return 1;
+ }
+
+ /* Alas. Undo changes. */
+ sk->forward_alloc -= amt*TCP_MEM_QUANTUM;
+ atomic_sub(amt, &tcp_memory_allocated);
+ return 0;
+}
+
+void __tcp_mem_reclaim(struct sock *sk)
+{
+ if (sk->forward_alloc >= TCP_MEM_QUANTUM) {
+ atomic_sub(sk->forward_alloc/TCP_MEM_QUANTUM, &tcp_memory_allocated);
+ sk->forward_alloc &= (TCP_MEM_QUANTUM-1);
+ if (tcp_memory_pressure &&
+ atomic_read(&tcp_memory_allocated) < sysctl_tcp_mem[0])
+ tcp_memory_pressure = 0;
+ }
+}
+
+void tcp_rfree(struct sk_buff *skb)
+{
+ struct sock *sk = skb->sk;
+
+ atomic_sub(skb->truesize, &sk->rmem_alloc);
+ sk->forward_alloc += skb->truesize;
+}
+
+/*
+ * LISTEN is a special case for poll..
+ */
+static __inline__ unsigned int tcp_listen_poll(struct sock *sk, poll_table *wait)
+{
+ return sk->tp_pinfo.af_tcp.accept_queue ? (POLLIN | POLLRDNORM) : 0;
+}
+
+/*
+ * Wait for a TCP event.
+ *
+ * Note that we don't need to lock the socket, as the upper poll layers
+ * take care of normal races (between the test and the event) and we don't
+ * go look at any of the socket buffers directly.
+ */
+unsigned int tcp_poll(struct file * file, struct socket *sock, poll_table *wait)
+{
+#if 0
+ unsigned int mask;
+ struct sock *sk = sock->sk;
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ poll_wait(file, sk->sleep, wait);
+ if (sk->state == TCP_LISTEN)
+ return tcp_listen_poll(sk, wait);
+
+ /* Socket is not locked. We are protected from async events
+ by poll logic and correct handling of state changes
+ made by another threads is impossible in any case.
+ */
+
+ mask = 0;
+ if (sk->err)
+ mask = POLLERR;
+
+ /*
+ * POLLHUP is certainly not done right. But poll() doesn't
+ * have a notion of HUP in just one direction, and for a
+ * socket the read side is more interesting.
+ *
+ * Some poll() documentation says that POLLHUP is incompatible
+ * with the POLLOUT/POLLWR flags, so somebody should check this
+ * all. But careful, it tends to be safer to return too many
+ * bits than too few, and you can easily break real applications
+ * if you don't tell them that something has hung up!
+ *
+ * Check-me.
+ *
+ * Check number 1. POLLHUP is _UNMASKABLE_ event (see UNIX98 and
+ * our fs/select.c). It means that after we received EOF,
+ * poll always returns immediately, making impossible poll() on write()
+ * in state CLOSE_WAIT. One solution is evident --- to set POLLHUP
+ * if and only if shutdown has been made in both directions.
+ * Actually, it is interesting to look how Solaris and DUX
+ * solve this dilemma. I would prefer, if PULLHUP were maskable,
+ * then we could set it on SND_SHUTDOWN. BTW examples given
+ * in Stevens' books assume exactly this behaviour, it explains
+ * why PULLHUP is incompatible with POLLOUT. --ANK
+ *
+ * NOTE. Check for TCP_CLOSE is added. The goal is to prevent
+ * blocking on fresh not-connected or disconnected socket. --ANK
+ */
+ if (sk->shutdown == SHUTDOWN_MASK || sk->state == TCP_CLOSE)
+ mask |= POLLHUP;
+ if (sk->shutdown & RCV_SHUTDOWN)
+ mask |= POLLIN | POLLRDNORM;
+
+ /* Connected? */
+ if ((1 << sk->state) & ~(TCPF_SYN_SENT|TCPF_SYN_RECV)) {
+ /* Potential race condition. If read of tp below will
+ * escape above sk->state, we can be illegally awaken
+ * in SYN_* states. */
+ if ((tp->rcv_nxt != tp->copied_seq) &&
+ (tp->urg_seq != tp->copied_seq ||
+ tp->rcv_nxt != tp->copied_seq+1 ||
+ sk->urginline || !tp->urg_data))
+ mask |= POLLIN | POLLRDNORM;
+
+ if (!(sk->shutdown & SEND_SHUTDOWN)) {
+ if (tcp_wspace(sk) >= tcp_min_write_space(sk)) {
+ mask |= POLLOUT | POLLWRNORM;
+ } else { /* send SIGIO later */
+ set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
+ set_bit(SOCK_NOSPACE, &sk->socket->flags);
+
+ /* Race breaker. If space is freed after
+ * wspace test but before the flags are set,
+ * IO signal will be lost.
+ */
+ if (tcp_wspace(sk) >= tcp_min_write_space(sk))
+ mask |= POLLOUT | POLLWRNORM;
+ }
+ }
+
+ if (tp->urg_data & TCP_URG_VALID)
+ mask |= POLLPRI;
+ }
+ return mask;
+#else
+ return 0;
+#endif
+}
+
+/*
+ * TCP socket write_space callback.
+ */
+void tcp_write_space(struct sock *sk)
+{
+#if 0
+ struct socket *sock = sk->socket;
+
+ if (tcp_wspace(sk) >= tcp_min_write_space(sk) && sock) {
+ clear_bit(SOCK_NOSPACE, &sock->flags);
+
+ if (sk->sleep && waitqueue_active(sk->sleep))
+ wake_up_interruptible(sk->sleep);
+
+ if (sock->fasync_list && !(sk->shutdown&SEND_SHUTDOWN))
+ sock_wake_async(sock, 2, POLL_OUT);
+ }
+#endif
+}
+
+int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int answ;
+
+ switch(cmd) {
+ case SIOCINQ:
+ if (sk->state == TCP_LISTEN)
+ return(-EINVAL);
+
+ lock_sock(sk);
+ if ((1<<sk->state) & (TCPF_SYN_SENT|TCPF_SYN_RECV))
+ answ = 0;
+ else if (sk->urginline || !tp->urg_data ||
+ before(tp->urg_seq,tp->copied_seq) ||
+ !before(tp->urg_seq,tp->rcv_nxt)) {
+ answ = tp->rcv_nxt - tp->copied_seq;
+
+ /* Subtract 1, if FIN is in queue. */
+ if (answ && !skb_queue_empty(&sk->receive_queue))
+ answ -= ((struct sk_buff*)sk->receive_queue.prev)->h.th->fin;
+ } else
+ answ = tp->urg_seq - tp->copied_seq;
+ release_sock(sk);
+ break;
+ case SIOCATMARK:
+ {
+ answ = tp->urg_data && tp->urg_seq == tp->copied_seq;
+ break;
+ }
+ case SIOCOUTQ:
+ if (sk->state == TCP_LISTEN)
+ return(-EINVAL);
+
+ if ((1<<sk->state) & (TCPF_SYN_SENT|TCPF_SYN_RECV))
+ answ = 0;
+ else
+ answ = tp->write_seq - tp->snd_una;
+ break;
+ default:
+ return(-ENOIOCTLCMD);
+ };
+
+ return put_user(answ, (int *)arg);
+#else
+return 0;
+#endif
+}
+
+
+int tcp_listen_start(struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct tcp_listen_opt *lopt;
+
+ sk->max_ack_backlog = 0;
+ sk->ack_backlog = 0;
+ tp->accept_queue = tp->accept_queue_tail = NULL;
+ tp->syn_wait_lock = RW_LOCK_UNLOCKED;
+ tcp_delack_init(tp);
+
+ lopt = kmalloc(sizeof(struct tcp_listen_opt), GFP_KERNEL);
+ if (!lopt)
+ return -ENOMEM;
+
+ memset(lopt, 0, sizeof(struct tcp_listen_opt));
+ for (lopt->max_qlen_log = 6; ; lopt->max_qlen_log++)
+ if ((1<<lopt->max_qlen_log) >= sysctl_max_syn_backlog)
+ break;
+
+ write_lock_bh(&tp->syn_wait_lock);
+ tp->listen_opt = lopt;
+ write_unlock_bh(&tp->syn_wait_lock);
+
+ /* There is race window here: we announce ourselves listening,
+ * but this transition is still not validated by get_port().
+ * It is OK, because this socket enters to hash table only
+ * after validation is complete.
+ */
+ sk->state = TCP_LISTEN;
+ if (sk->prot->get_port(sk, sk->num) == 0) {
+ sk->sport = htons(sk->num);
+
+ sk_dst_reset(sk);
+ sk->prot->hash(sk);
+
+ return 0;
+ }
+
+ sk->state = TCP_CLOSE;
+ write_lock_bh(&tp->syn_wait_lock);
+ tp->listen_opt = NULL;
+ write_unlock_bh(&tp->syn_wait_lock);
+ kfree(lopt);
+ return -EADDRINUSE;
+#endif
+}
+
+/*
+ * This routine closes sockets which have been at least partially
+ * opened, but not yet accepted.
+ */
+
+static void tcp_listen_stop (struct sock *sk)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct tcp_listen_opt *lopt = tp->listen_opt;
+ struct open_request *acc_req = tp->accept_queue;
+ struct open_request *req;
+ int i;
+
+ tcp_delete_keepalive_timer(sk);
+
+ /* make all the listen_opt local to us */
+ write_lock_bh(&tp->syn_wait_lock);
+ tp->listen_opt =NULL;
+ write_unlock_bh(&tp->syn_wait_lock);
+ tp->accept_queue = tp->accept_queue_tail = NULL;
+
+ if (lopt->qlen) {
+ for (i=0; i<TCP_SYNQ_HSIZE; i++) {
+ while ((req = lopt->syn_table[i]) != NULL) {
+ lopt->syn_table[i] = req->dl_next;
+ lopt->qlen--;
+ tcp_openreq_free(req);
+
+ /* Following specs, it would be better either to send FIN
+ * (and enter FIN-WAIT-1, it is normal close)
+ * or to send active reset (abort).
+ * Certainly, it is pretty dangerous while synflood, but it is
+ * bad justification for our negligence 8)
+ * To be honest, we are not able to make either
+ * of the variants now. --ANK
+ */
+ }
+ }
+ }
+ BUG_TRAP(lopt->qlen == 0);
+
+ kfree(lopt);
+
+ while ((req=acc_req) != NULL) {
+ struct sock *child = req->sk;
+
+ acc_req = req->dl_next;
+
+ local_bh_disable();
+ bh_lock_sock(child);
+ BUG_TRAP(child->lock.users==0);
+ sock_hold(child);
+
+ tcp_disconnect(child, O_NONBLOCK);
+
+ sock_orphan(child);
+
+ atomic_inc(&tcp_orphan_count);
+
+ tcp_destroy_sock(child);
+
+ bh_unlock_sock(child);
+ local_bh_enable();
+ sock_put(child);
+
+ tcp_acceptq_removed(sk);
+ tcp_openreq_fastfree(req);
+ }
+ BUG_TRAP(sk->ack_backlog == 0);
+#endif
+}
+
+/*
+ * Wait for a socket to get into the connected state
+ *
+ * Note: Must be called with the socket locked.
+ */
+static int wait_for_tcp_connect(struct sock * sk, int flags, long *timeo_p)
+{
+#if 0
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, tsk);
+
+ while((1 << sk->state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) {
+ if(sk->err)
+ return sock_error(sk);
+ if((1 << sk->state) &
+ ~(TCPF_SYN_SENT | TCPF_SYN_RECV))
+ return -EPIPE;
+ if(!*timeo_p)
+ return -EAGAIN;
+ if(signal_pending(tsk))
+ return sock_intr_errno(*timeo_p);
+
+ __set_task_state(tsk, TASK_INTERRUPTIBLE);
+ add_wait_queue(sk->sleep, &wait);
+ sk->tp_pinfo.af_tcp.write_pending++;
+
+ release_sock(sk);
+ *timeo_p = schedule_timeout(*timeo_p);
+ lock_sock(sk);
+
+ __set_task_state(tsk, TASK_RUNNING);
+ remove_wait_queue(sk->sleep, &wait);
+ sk->tp_pinfo.af_tcp.write_pending--;
+ }
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+static inline int tcp_memory_free(struct sock *sk)
+{
+ return sk->wmem_queued < sk->sndbuf;
+}
+
+/*
+ * Wait for more memory for a socket
+ */
+static int wait_for_tcp_memory(struct sock * sk, long *timeo)
+{
+#if 0
+ int err = 0;
+ long vm_wait = 0;
+ long current_timeo = *timeo;
+ DECLARE_WAITQUEUE(wait, current);
+
+ if (tcp_memory_free(sk))
+ current_timeo = vm_wait = (net_random()%(HZ/5))+2;
+
+ add_wait_queue(sk->sleep, &wait);
+ for (;;) {
+ set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
+
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if (sk->err || (sk->shutdown & SEND_SHUTDOWN))
+ goto do_error;
+ if (!*timeo)
+ goto do_nonblock;
+ if (signal_pending(current))
+ goto do_interrupted;
+ clear_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
+ if (tcp_memory_free(sk) && !vm_wait)
+ break;
+
+ set_bit(SOCK_NOSPACE, &sk->socket->flags);
+ sk->tp_pinfo.af_tcp.write_pending++;
+ release_sock(sk);
+ if (!tcp_memory_free(sk) || vm_wait)
+ current_timeo = schedule_timeout(current_timeo);
+ lock_sock(sk);
+ sk->tp_pinfo.af_tcp.write_pending--;
+
+ if (vm_wait) {
+ vm_wait -= current_timeo;
+ current_timeo = *timeo;
+ if (current_timeo != MAX_SCHEDULE_TIMEOUT &&
+ (current_timeo -= vm_wait) < 0)
+ current_timeo = 0;
+ vm_wait = 0;
+ }
+ *timeo = current_timeo;
+ }
+out:
+ current->state = TASK_RUNNING;
+ remove_wait_queue(sk->sleep, &wait);
+ return err;
+
+do_error:
+ err = -EPIPE;
+ goto out;
+do_nonblock:
+ err = -EAGAIN;
+ goto out;
+do_interrupted:
+ err = sock_intr_errno(*timeo);
+ goto out;
+#endif
+}
+
+ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, size_t psize, int flags);
+
+static inline int
+can_coalesce(struct sk_buff *skb, int i, struct page *page, int off)
+{
+#if 0
+ if (i) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1];
+ return page == frag->page &&
+ off == frag->page_offset+frag->size;
+ }
+ return 0;
+#else
+return 0;
+#endif
+}
+
+static inline void
+fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size)
+{
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ frag->page = page;
+ frag->page_offset = off;
+ frag->size = size;
+ skb_shinfo(skb)->nr_frags = i+1;
+}
+
+static inline void tcp_mark_push(struct tcp_opt *tp, struct sk_buff *skb)
+{
+ TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
+ tp->pushed_seq = tp->write_seq;
+}
+
+static inline int forced_push(struct tcp_opt *tp)
+{
+ return after(tp->write_seq, tp->pushed_seq + (tp->max_window>>1));
+}
+
+static inline void
+skb_entail(struct sock *sk, struct tcp_opt *tp, struct sk_buff *skb)
+{
+ skb->csum = 0;
+ TCP_SKB_CB(skb)->seq = tp->write_seq;
+ TCP_SKB_CB(skb)->end_seq = tp->write_seq;
+ TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
+ TCP_SKB_CB(skb)->sacked = 0;
+ __skb_queue_tail(&sk->write_queue, skb);
+ tcp_charge_skb(sk, skb);
+ if (tp->send_head == NULL)
+ tp->send_head = skb;
+}
+
+static inline void
+tcp_mark_urg(struct tcp_opt *tp, int flags, struct sk_buff *skb)
+{
+#if 0
+ if (flags & MSG_OOB) {
+ tp->urg_mode = 1;
+ tp->snd_up = tp->write_seq;
+ TCP_SKB_CB(skb)->sacked |= TCPCB_URG;
+ }
+#endif
+}
+
+static inline void
+tcp_push(struct sock *sk, struct tcp_opt *tp, int flags, int mss_now, int nonagle)
+{
+#if 0
+ if (tp->send_head) {
+ struct sk_buff *skb = sk->write_queue.prev;
+ if (!(flags&MSG_MORE) || forced_push(tp))
+ tcp_mark_push(tp, skb);
+ tcp_mark_urg(tp, flags, skb);
+ __tcp_push_pending_frames(sk, tp, mss_now, (flags&MSG_MORE) ? 2 : nonagle);
+ }
+#endif
+}
+
+static int tcp_error(struct sock *sk, int flags, int err)
+{
+#if 0
+ if (err == -EPIPE)
+ err = sock_error(sk) ? : -EPIPE;
+ if (err == -EPIPE && !(flags&MSG_NOSIGNAL))
+ send_sig(SIGPIPE, current, 0);
+ return err;
+#else
+ return 0;
+#endif
+}
+
+ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset, size_t psize, int flags)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int mss_now;
+ int err;
+ ssize_t copied;
+ long timeo = sock_sndtimeo(sk, flags&MSG_DONTWAIT);
+
+ /* Wait for a connection to finish. */
+ if ((1 << sk->state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))
+ if((err = wait_for_tcp_connect(sk, 0, &timeo)) != 0)
+ goto out_err;
+
+ clear_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
+
+ mss_now = tcp_current_mss(sk);
+ copied = 0;
+
+ err = -EPIPE;
+ if (sk->err || (sk->shutdown & SEND_SHUTDOWN))
+ goto do_error;
+
+ while (psize > 0) {
+ struct sk_buff *skb = sk->write_queue.prev;
+ int offset, size, copy, i;
+ struct page *page;
+
+ page = pages[poffset/PAGE_SIZE];
+ offset = poffset % PAGE_SIZE;
+ size = min_t(size_t, psize, PAGE_SIZE-offset);
+
+ if (tp->send_head==NULL || (copy = mss_now - skb->len) <= 0) {
+new_segment:
+ if (!tcp_memory_free(sk))
+ goto wait_for_sndbuf;
+
+ skb = tcp_alloc_pskb(sk, 0, tp->mss_cache, sk->allocation);
+ if (skb == NULL)
+ goto wait_for_memory;
+
+ skb_entail(sk, tp, skb);
+ copy = mss_now;
+ }
+
+ if (copy > size)
+ copy = size;
+
+ i = skb_shinfo(skb)->nr_frags;
+ if (can_coalesce(skb, i, page, offset)) {
+ skb_shinfo(skb)->frags[i-1].size += copy;
+ } else if (i < MAX_SKB_FRAGS) {
+ get_page(page);
+ fill_page_desc(skb, i, page, offset, copy);
+ } else {
+ tcp_mark_push(tp, skb);
+ goto new_segment;
+ }
+
+ skb->len += copy;
+ skb->data_len += copy;
+ skb->ip_summed = CHECKSUM_HW;
+ tp->write_seq += copy;
+ TCP_SKB_CB(skb)->end_seq += copy;
+
+ if (!copied)
+ TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_PSH;
+
+ copied += copy;
+ poffset += copy;
+ if (!(psize -= copy))
+ goto out;
+
+ if (skb->len != mss_now || (flags&MSG_OOB))
+ continue;
+
+ if (forced_push(tp)) {
+ tcp_mark_push(tp, skb);
+ __tcp_push_pending_frames(sk, tp, mss_now, 1);
+ } else if (skb == tp->send_head)
+ tcp_push_one(sk, mss_now);
+ continue;
+
+wait_for_sndbuf:
+ set_bit(SOCK_NOSPACE, &sk->socket->flags);
+wait_for_memory:
+ if (copied)
+ tcp_push(sk, tp, flags&~MSG_MORE, mss_now, 1);
+
+ if ((err = wait_for_tcp_memory(sk, &timeo)) != 0)
+ goto do_error;
+
+ mss_now = tcp_current_mss(sk);
+ }
+
+out:
+ if (copied)
+ tcp_push(sk, tp, flags, mss_now, tp->nonagle);
+ return copied;
+
+do_error:
+ if (copied)
+ goto out;
+out_err:
+ return tcp_error(sk, flags, err);
+#else
+return 0;
+#endif
+}
+
+ssize_t tcp_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags)
+{
+#if 0
+ ssize_t res;
+ struct sock *sk = sock->sk;
+
+#define TCP_ZC_CSUM_FLAGS (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)
+
+ if (!(sk->route_caps & NETIF_F_SG) ||
+ !(sk->route_caps & TCP_ZC_CSUM_FLAGS))
+ return sock_no_sendpage(sock, page, offset, size, flags);
+
+#undef TCP_ZC_CSUM_FLAGS
+
+ lock_sock(sk);
+ TCP_CHECK_TIMER(sk);
+ res = do_tcp_sendpages(sk, &page, offset, size, flags);
+ TCP_CHECK_TIMER(sk);
+ release_sock(sk);
+ return res;
+#else
+ return 0;
+#endif
+}
+
+#define TCP_PAGE(sk) (sk->tp_pinfo.af_tcp.sndmsg_page)
+#define TCP_OFF(sk) (sk->tp_pinfo.af_tcp.sndmsg_off)
+
+static inline int
+tcp_copy_to_page(struct sock *sk, char *from, struct sk_buff *skb,
+ struct page *page, int off, int copy)
+{
+ int err = 0;
+ unsigned int csum;
+
+ csum = csum_and_copy_from_user(from, page_address(page)+off,
+ copy, 0, &err);
+ if (!err) {
+ if (skb->ip_summed == CHECKSUM_NONE)
+ skb->csum = csum_block_add(skb->csum, csum, skb->len);
+ skb->len += copy;
+ skb->data_len += copy;
+ skb->truesize += copy;
+ sk->wmem_queued += copy;
+ sk->forward_alloc -= copy;
+ }
+ return err;
+}
+
+static inline int
+skb_add_data(struct sk_buff *skb, char *from, int copy)
+{
+#if 0
+ int err = 0;
+ unsigned int csum;
+ int off = skb->len;
+
+ csum = csum_and_copy_from_user(from, skb_put(skb, copy),
+ copy, 0, &err);
+ if (!err) {
+ skb->csum = csum_block_add(skb->csum, csum, off);
+ return 0;
+ }
+
+ __skb_trim(skb, off);
+ return -EFAULT;
+#else
+return 0;
+#endif
+}
+
+static inline int select_size(struct sock *sk, struct tcp_opt *tp)
+{
+#if 0
+ int tmp = tp->mss_cache;
+
+ if (sk->route_caps&NETIF_F_SG) {
+ int pgbreak = SKB_MAX_HEAD(MAX_TCP_HEADER);
+
+ if (tmp >= pgbreak && tmp <= pgbreak + (MAX_SKB_FRAGS-1)*PAGE_SIZE)
+ tmp = pgbreak;
+ }
+ return tmp;
+#else
+ return 0;
+#endif
+}
+
+int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
+{
+#if 0
+ struct iovec *iov;
+ struct tcp_opt *tp;
+ struct sk_buff *skb;
+ int iovlen, flags;
+ int mss_now;
+ int err, copied;
+ long timeo;
+
+ tp = &(sk->tp_pinfo.af_tcp);
+
+ lock_sock(sk);
+ TCP_CHECK_TIMER(sk);
+
+ flags = msg->msg_flags;
+ timeo = sock_sndtimeo(sk, flags&MSG_DONTWAIT);
+
+ /* Wait for a connection to finish. */
+ if ((1 << sk->state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))
+ if((err = wait_for_tcp_connect(sk, flags, &timeo)) != 0)
+ goto out_err;
+
+ /* This should be in poll */
+ clear_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);
+
+ mss_now = tcp_current_mss(sk);
+
+ /* Ok commence sending. */
+ iovlen = msg->msg_iovlen;
+ iov = msg->msg_iov;
+ copied = 0;
+
+ err = -EPIPE;
+ if (sk->err || (sk->shutdown&SEND_SHUTDOWN))
+ goto do_error;
+
+ while (--iovlen >= 0) {
+ int seglen=iov->iov_len;
+ unsigned char * from=iov->iov_base;
+
+ iov++;
+
+ while (seglen > 0) {
+ int copy;
+
+ skb = sk->write_queue.prev;
+
+ if (tp->send_head == NULL ||
+ (copy = mss_now - skb->len) <= 0) {
+
+new_segment:
+ /* Allocate new segment. If the interface is SG,
+ * allocate skb fitting to single page.
+ */
+ if (!tcp_memory_free(sk))
+ goto wait_for_sndbuf;
+
+ skb = tcp_alloc_pskb(sk, select_size(sk, tp), 0, sk->allocation);
+ if (skb == NULL)
+ goto wait_for_memory;
+
+ skb_entail(sk, tp, skb);
+ copy = mss_now;
+ }
+
+ /* Try to append data to the end of skb. */
+ if (copy > seglen)
+ copy = seglen;
+
+ /* Where to copy to? */
+ if (skb_tailroom(skb) > 0) {
+ /* We have some space in skb head. Superb! */
+ if (copy > skb_tailroom(skb))
+ copy = skb_tailroom(skb);
+ if ((err = skb_add_data(skb, from, copy)) != 0)
+ goto do_fault;
+ } else {
+ int merge = 0;
+ int i = skb_shinfo(skb)->nr_frags;
+ struct page *page = TCP_PAGE(sk);
+ int off = TCP_OFF(sk);
+
+ if (can_coalesce(skb, i, page, off) && off != PAGE_SIZE) {
+ /* We can extend the last page fragment. */
+ merge = 1;
+ } else if (i == MAX_SKB_FRAGS ||
+ (i == 0 && !(sk->route_caps&NETIF_F_SG))) {
+ /* Need to add new fragment and cannot
+ * do this because interface is non-SG,
+ * or because all the page slots are busy.
+ */
+ tcp_mark_push(tp, skb);
+ goto new_segment;
+ } else if (page) {
+ /* If page is cached, align
+ * offset to L1 cache boundary
+ */
+ off = (off+L1_CACHE_BYTES-1)&~(L1_CACHE_BYTES-1);
+ if (off == PAGE_SIZE) {
+ put_page(page);
+ TCP_PAGE(sk) = page = NULL;
+ }
+ }
+
+ if (!page) {
+ /* Allocate new cache page. */
+ if (!(page=tcp_alloc_page(sk)))
+ goto wait_for_memory;
+ off = 0;
+ }
+
+ if (copy > PAGE_SIZE-off)
+ copy = PAGE_SIZE-off;
+
+ /* Time to copy data. We are close to the end! */
+ err = tcp_copy_to_page(sk, from, skb, page, off, copy);
+ if (err) {
+ /* If this page was new, give it to the
+ * socket so it does not get leaked.
+ */
+ if (TCP_PAGE(sk) == NULL) {
+ TCP_PAGE(sk) = page;
+ TCP_OFF(sk) = 0;
+ }
+ goto do_error;
+ }
+
+ /* Update the skb. */
+ if (merge) {
+ skb_shinfo(skb)->frags[i-1].size += copy;
+ } else {
+ fill_page_desc(skb, i, page, off, copy);
+ if (TCP_PAGE(sk)) {
+ get_page(page);
+ } else if (off + copy < PAGE_SIZE) {
+ get_page(page);
+ TCP_PAGE(sk) = page;
+ }
+ }
+
+ TCP_OFF(sk) = off+copy;
+ }
+
+ if (!copied)
+ TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_PSH;
+
+ tp->write_seq += copy;
+ TCP_SKB_CB(skb)->end_seq += copy;
+
+ from += copy;
+ copied += copy;
+ if ((seglen -= copy) == 0 && iovlen == 0)
+ goto out;
+
+ if (skb->len != mss_now || (flags&MSG_OOB))
+ continue;
+
+ if (forced_push(tp)) {
+ tcp_mark_push(tp, skb);
+ __tcp_push_pending_frames(sk, tp, mss_now, 1);
+ } else if (skb == tp->send_head)
+ tcp_push_one(sk, mss_now);
+ continue;
+
+wait_for_sndbuf:
+ set_bit(SOCK_NOSPACE, &sk->socket->flags);
+wait_for_memory:
+ if (copied)
+ tcp_push(sk, tp, flags&~MSG_MORE, mss_now, 1);
+
+ if ((err = wait_for_tcp_memory(sk, &timeo)) != 0)
+ goto do_error;
+
+ mss_now = tcp_current_mss(sk);
+ }
+ }
+
+out:
+ if (copied)
+ tcp_push(sk, tp, flags, mss_now, tp->nonagle);
+ TCP_CHECK_TIMER(sk);
+ release_sock(sk);
+ return copied;
+
+do_fault:
+ if (skb->len == 0) {
+ if (tp->send_head == skb)
+ tp->send_head = NULL;
+ __skb_unlink(skb, skb->list);
+ tcp_free_skb(sk, skb);
+ }
+
+do_error:
+ if (copied)
+ goto out;
+out_err:
+ err = tcp_error(sk, flags, err);
+ TCP_CHECK_TIMER(sk);
+ release_sock(sk);
+ return err;
+#else
+ return 0;
+#endif
+}
+
+/*
+ * Handle reading urgent data. BSD has very simple semantics for
+ * this, no blocking and very strange errors 8)
+ */
+
+static int tcp_recv_urg(struct sock * sk, long timeo,
+ struct msghdr *msg, int len, int flags,
+ int *addr_len)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ /* No URG data to read. */
+ if (sk->urginline || !tp->urg_data || tp->urg_data == TCP_URG_READ)
+ return -EINVAL; /* Yes this is right ! */
+
+ if (sk->state==TCP_CLOSE && !sk->done)
+ return -ENOTCONN;
+
+ if (tp->urg_data & TCP_URG_VALID) {
+ int err = 0;
+ char c = tp->urg_data;
+
+ if (!(flags & MSG_PEEK))
+ tp->urg_data = TCP_URG_READ;
+
+ /* Read urgent data. */
+ msg->msg_flags|=MSG_OOB;
+
+ if(len>0) {
+ if (!(flags & MSG_TRUNC))
+ err = memcpy_toiovec(msg->msg_iov, &c, 1);
+ len = 1;
+ } else
+ msg->msg_flags|=MSG_TRUNC;
+
+ return err ? -EFAULT : len;
+ }
+
+ if (sk->state == TCP_CLOSE || (sk->shutdown & RCV_SHUTDOWN))
+ return 0;
+
+ /* Fixed the recv(..., MSG_OOB) behaviour. BSD docs and
+ * the available implementations agree in this case:
+ * this call should never block, independent of the
+ * blocking state of the socket.
+ * Mike <pall@rz.uni-karlsruhe.de>
+ */
+ return -EAGAIN;
+#else
+return 0;
+#endif
+}
+
+/*
+ * Release a skb if it is no longer needed. This routine
+ * must be called with interrupts disabled or with the
+ * socket locked so that the sk_buff queue operation is ok.
+ */
+
+static inline void tcp_eat_skb(struct sock *sk, struct sk_buff * skb)
+{
+#if 0
+ __skb_unlink(skb, &sk->receive_queue);
+ __kfree_skb(skb);
+#endif
+}
+
+/* Clean up the receive buffer for full frames taken by the user,
+ * then send an ACK if necessary. COPIED is the number of bytes
+ * tcp_recvmsg has given to the user so far, it speeds up the
+ * calculation of whether or not we must ACK for the sake of
+ * a window update.
+ */
+static void cleanup_rbuf(struct sock *sk, int copied)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int time_to_ack = 0;
+
+#if TCP_DEBUG
+ struct sk_buff *skb = skb_peek(&sk->receive_queue);
+
+ BUG_TRAP(skb==NULL || before(tp->copied_seq, TCP_SKB_CB(skb)->end_seq));
+#endif
+
+ if (tcp_ack_scheduled(tp)) {
+ /* Delayed ACKs frequently hit locked sockets during bulk receive. */
+ if (tp->ack.blocked
+ /* Once-per-two-segments ACK was not sent by tcp_input.c */
+ || tp->rcv_nxt - tp->rcv_wup > tp->ack.rcv_mss
+ /*
+ * If this read emptied read buffer, we send ACK, if
+ * connection is not bidirectional, user drained
+ * receive buffer and there was a small segment
+ * in queue.
+ */
+ || (copied > 0 &&
+ (tp->ack.pending&TCP_ACK_PUSHED) &&
+ !tp->ack.pingpong &&
+ atomic_read(&sk->rmem_alloc) == 0)) {
+ time_to_ack = 1;
+ }
+ }
+
+ /* We send an ACK if we can now advertise a non-zero window
+ * which has been raised "significantly".
+ *
+ * Even if window raised up to infinity, do not send window open ACK
+ * in states, where we will not receive more. It is useless.
+ */
+ if(copied > 0 && !time_to_ack && !(sk->shutdown&RCV_SHUTDOWN)) {
+ __u32 rcv_window_now = tcp_receive_window(tp);
+
+ /* Optimize, __tcp_select_window() is not cheap. */
+ if (2*rcv_window_now <= tp->window_clamp) {
+ __u32 new_window = __tcp_select_window(sk);
+
+ /* Send ACK now, if this read freed lots of space
+ * in our buffer. Certainly, new_window is new window.
+ * We can advertise it now, if it is not less than current one.
+ * "Lots" means "at least twice" here.
+ */
+ if(new_window && new_window >= 2*rcv_window_now)
+ time_to_ack = 1;
+ }
+ }
+ if (time_to_ack)
+ tcp_send_ack(sk);
+#endif
+}
+
+/* Now socket state including sk->err is changed only under lock,
+ * hence we may omit checks after joining wait queue.
+ * We check receive queue before schedule() only as optimization;
+ * it is very likely that release_sock() added new data.
+ */
+
+static long tcp_data_wait(struct sock *sk, long timeo)
+{
+#if 0
+ DECLARE_WAITQUEUE(wait, current);
+
+ add_wait_queue(sk->sleep, &wait);
+
+ __set_current_state(TASK_INTERRUPTIBLE);
+
+ set_bit(SOCK_ASYNC_WAITDATA, &sk->socket->flags);
+ release_sock(sk);
+
+ if (skb_queue_empty(&sk->receive_queue))
+ timeo = schedule_timeout(timeo);
+
+ lock_sock(sk);
+ clear_bit(SOCK_ASYNC_WAITDATA, &sk->socket->flags);
+
+ remove_wait_queue(sk->sleep, &wait);
+ __set_current_state(TASK_RUNNING);
+ return timeo;
+#else
+ return 0;
+#endif
+}
+
+static void tcp_prequeue_process(struct sock *sk)
+{
+#if 0
+ struct sk_buff *skb;
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+ net_statistics[smp_processor_id()*2+1].TCPPrequeued += skb_queue_len(&tp->ucopy.prequeue);
+
+ /* RX process wants to run with disabled BHs, though it is not necessary */
+ local_bh_disable();
+ while ((skb = __skb_dequeue(&tp->ucopy.prequeue)) != NULL)
+ sk->backlog_rcv(sk, skb);
+ local_bh_enable();
+
+ /* Clear memory counter. */
+ tp->ucopy.memory = 0;
+#endif
+}
+
+static inline
+struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
+{
+#if 0
+ struct sk_buff *skb;
+ u32 offset;
+
+ skb_queue_walk(&sk->receive_queue, skb) {
+ offset = seq - TCP_SKB_CB(skb)->seq;
+ if (skb->h.th->syn)
+ offset--;
+ if (offset < skb->len || skb->h.th->fin) {
+ *off = offset;
+ return skb;
+ }
+ }
+ return NULL;
+#else
+ return NULL;
+#endif
+}
+
+/*
+ * This routine provides an alternative to tcp_recvmsg() for routines
+ * that would like to handle copying from skbuffs directly in 'sendfile'
+ * fashion.
+ * Note:
+ * - It is assumed that the socket was locked by the caller.
+ * - The routine does not block.
+ * - At present, there is no support for reading OOB data
+ * or for 'peeking' the socket using this routine
+ * (although both would be easy to implement).
+ */
+int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
+ sk_read_actor_t recv_actor)
+{
+#if 0
+ struct sk_buff *skb;
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ u32 seq = tp->copied_seq;
+ u32 offset;
+ int copied = 0;
+
+ if (sk->state == TCP_LISTEN)
+ return -ENOTCONN;
+ while ((skb = tcp_recv_skb(sk, seq, &offset)) != NULL) {
+ if (offset < skb->len) {
+ size_t used, len;
+
+ len = skb->len - offset;
+ /* Stop reading if we hit a patch of urgent data */
+ if (tp->urg_data) {
+ u32 urg_offset = tp->urg_seq - seq;
+ if (urg_offset < len)
+ len = urg_offset;
+ if (!len)
+ break;
+ }
+ used = recv_actor(desc, skb, offset, len);
+ if (used <= len) {
+ seq += used;
+ copied += used;
+ offset += used;
+ }
+ if (offset != skb->len)
+ break;
+ }
+ if (skb->h.th->fin) {
+ tcp_eat_skb(sk, skb);
+ ++seq;
+ break;
+ }
+ tcp_eat_skb(sk, skb);
+ if (!desc->count)
+ break;
+ }
+ tp->copied_seq = seq;
+ /* Clean up data we have read: This will do ACK frames. */
+ if (copied)
+ cleanup_rbuf(sk, copied);
+ return copied;
+#else
+#endif
+}
+
+/*
+ * This routine copies from a sock struct into the user buffer.
+ *
+ * Technical note: in 2.3 we work on _locked_ socket, so that
+ * tricks with *seq access order and skb->users are not required.
+ * Probably, code can be easily improved even more.
+ */
+
+int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
+ int len, int nonblock, int flags, int *addr_len)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int copied = 0;
+ u32 peek_seq;
+ u32 *seq;
+ unsigned long used;
+ int err;
+ int target; /* Read at least this many bytes */
+ long timeo;
+ struct task_struct *user_recv = NULL;
+
+ lock_sock(sk);
+
+ TCP_CHECK_TIMER(sk);
+
+ err = -ENOTCONN;
+ if (sk->state == TCP_LISTEN)
+ goto out;
+
+ timeo = sock_rcvtimeo(sk, nonblock);
+
+ /* Urgent data needs to be handled specially. */
+ if (flags & MSG_OOB)
+ goto recv_urg;
+
+ seq = &tp->copied_seq;
+ if (flags & MSG_PEEK) {
+ peek_seq = tp->copied_seq;
+ seq = &peek_seq;
+ }
+
+ target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
+
+ do {
+ struct sk_buff * skb;
+ u32 offset;
+
+ /* Are we at urgent data? Stop if we have read anything. */
+ if (copied && tp->urg_data && tp->urg_seq == *seq)
+ break;
+
+ /* We need to check signals first, to get correct SIGURG
+ * handling. FIXME: Need to check this doesn't impact 1003.1g
+ * and move it down to the bottom of the loop
+ */
+ if (signal_pending(current)) {
+ if (copied)
+ break;
+ copied = timeo ? sock_intr_errno(timeo) : -EAGAIN;
+ break;
+ }
+
+ /* Next get a buffer. */
+
+ skb = skb_peek(&sk->receive_queue);
+ do {
+ if (!skb)
+ break;
+
+ /* Now that we have two receive queues this
+ * shouldn't happen.
+ */
+ if (before(*seq, TCP_SKB_CB(skb)->seq)) {
+ printk(KERN_INFO "recvmsg bug: copied %X seq %X\n",
+ *seq, TCP_SKB_CB(skb)->seq);
+ break;
+ }
+ offset = *seq - TCP_SKB_CB(skb)->seq;
+ if (skb->h.th->syn)
+ offset--;
+ if (offset < skb->len)
+ goto found_ok_skb;
+ if (skb->h.th->fin)
+ goto found_fin_ok;
+ BUG_TRAP(flags&MSG_PEEK);
+ skb = skb->next;
+ } while (skb != (struct sk_buff *)&sk->receive_queue);
+
+ /* Well, if we have backlog, try to process it now yet. */
+
+ if (copied >= target && sk->backlog.tail == NULL)
+ break;
+
+ if (copied) {
+ if (sk->err ||
+ sk->state == TCP_CLOSE ||
+ (sk->shutdown & RCV_SHUTDOWN) ||
+ !timeo ||
+ (flags & MSG_PEEK))
+ break;
+ } else {
+ if (sk->done)
+ break;
+
+ if (sk->err) {
+ copied = sock_error(sk);
+ break;
+ }
+
+ if (sk->shutdown & RCV_SHUTDOWN)
+ break;
+
+ if (sk->state == TCP_CLOSE) {
+ if (!sk->done) {
+ /* This occurs when user tries to read
+ * from never connected socket.
+ */
+ copied = -ENOTCONN;
+ break;
+ }
+ break;
+ }
+
+ if (!timeo) {
+ copied = -EAGAIN;
+ break;
+ }
+ }
+
+ cleanup_rbuf(sk, copied);
+
+ if (tp->ucopy.task == user_recv) {
+ /* Install new reader */
+ if (user_recv == NULL && !(flags&(MSG_TRUNC|MSG_PEEK))) {
+ user_recv = current;
+ tp->ucopy.task = user_recv;
+ tp->ucopy.iov = msg->msg_iov;
+ }
+
+ tp->ucopy.len = len;
+
+ BUG_TRAP(tp->copied_seq == tp->rcv_nxt || (flags&(MSG_PEEK|MSG_TRUNC)));
+
+ /* Ugly... If prequeue is not empty, we have to
+ * process it before releasing socket, otherwise
+ * order will be broken at second iteration.
+ * More elegant solution is required!!!
+ *
+ * Look: we have the following (pseudo)queues:
+ *
+ * 1. packets in flight
+ * 2. backlog
+ * 3. prequeue
+ * 4. receive_queue
+ *
+ * Each queue can be processed only if the next ones
+ * are empty. At this point we have empty receive_queue.
+ * But prequeue _can_ be not empty after second iteration,
+ * when we jumped to start of loop because backlog
+ * processing added something to receive_queue.
+ * We cannot release_sock(), because backlog contains
+ * packets arrived _after_ prequeued ones.
+ *
+ * Shortly, algorithm is clear --- to process all
+ * the queues in order. We could make it more directly,
+ * requeueing packets from backlog to prequeue, if
+ * is not empty. It is more elegant, but eats cycles,
+ * unfortunately.
+ */
+ if (skb_queue_len(&tp->ucopy.prequeue))
+ goto do_prequeue;
+
+ /* __ Set realtime policy in scheduler __ */
+ }
+
+ if (copied >= target) {
+ /* Do not sleep, just process backlog. */
+ release_sock(sk);
+ lock_sock(sk);
+ } else {
+ timeo = tcp_data_wait(sk, timeo);
+ }
+
+ if (user_recv) {
+ int chunk;
+
+ /* __ Restore normal policy in scheduler __ */
+
+ if ((chunk = len - tp->ucopy.len) != 0) {
+ net_statistics[smp_processor_id()*2+1].TCPDirectCopyFromBacklog += chunk;
+ len -= chunk;
+ copied += chunk;
+ }
+
+ if (tp->rcv_nxt == tp->copied_seq &&
+ skb_queue_len(&tp->ucopy.prequeue)) {
+do_prequeue:
+ tcp_prequeue_process(sk);
+
+ if ((chunk = len - tp->ucopy.len) != 0) {
+ net_statistics[smp_processor_id()*2+1].TCPDirectCopyFromPrequeue += chunk;
+ len -= chunk;
+ copied += chunk;
+ }
+ }
+ }
+ if ((flags & MSG_PEEK) && peek_seq != tp->copied_seq) {
+ if (net_ratelimit())
+ printk(KERN_DEBUG "TCP(%s:%d): Application bug, race in MSG_PEEK.\n",
+ current->comm, current->pid);
+ peek_seq = tp->copied_seq;
+ }
+ continue;
+
+ found_ok_skb:
+ /* Ok so how much can we use? */
+ used = skb->len - offset;
+ if (len < used)
+ used = len;
+
+ /* Do we have urgent data here? */
+ if (tp->urg_data) {
+ u32 urg_offset = tp->urg_seq - *seq;
+ if (urg_offset < used) {
+ if (!urg_offset) {
+ if (!sk->urginline) {
+ ++*seq;
+ offset++;
+ used--;
+ if (!used)
+ goto skip_copy;
+ }
+ } else
+ used = urg_offset;
+ }
+ }
+
+ if (!(flags&MSG_TRUNC)) {
+ err = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, used);
+ if (err) {
+ /* Exception. Bailout! */
+ if (!copied)
+ copied = -EFAULT;
+ break;
+ }
+ }
+
+ *seq += used;
+ copied += used;
+ len -= used;
+
+skip_copy:
+ if (tp->urg_data && after(tp->copied_seq,tp->urg_seq)) {
+ tp->urg_data = 0;
+ tcp_fast_path_check(sk, tp);
+ }
+ if (used + offset < skb->len)
+ continue;
+
+ if (skb->h.th->fin)
+ goto found_fin_ok;
+ if (!(flags & MSG_PEEK))
+ tcp_eat_skb(sk, skb);
+ continue;
+
+ found_fin_ok:
+ /* Process the FIN. */
+ ++*seq;
+ if (!(flags & MSG_PEEK))
+ tcp_eat_skb(sk, skb);
+ break;
+ } while (len > 0);
+
+ if (user_recv) {
+ if (skb_queue_len(&tp->ucopy.prequeue)) {
+ int chunk;
+
+ tp->ucopy.len = copied > 0 ? len : 0;
+
+ tcp_prequeue_process(sk);
+
+ if (copied > 0 && (chunk = len - tp->ucopy.len) != 0) {
+ net_statistics[smp_processor_id()*2+1].TCPDirectCopyFromPrequeue += chunk;
+ len -= chunk;
+ copied += chunk;
+ }
+ }
+
+ tp->ucopy.task = NULL;
+ tp->ucopy.len = 0;
+ }
+
+ /* According to UNIX98, msg_name/msg_namelen are ignored
+ * on connected socket. I was just happy when found this 8) --ANK
+ */
+
+ /* Clean up data we have read: This will do ACK frames. */
+ cleanup_rbuf(sk, copied);
+
+ TCP_CHECK_TIMER(sk);
+ release_sock(sk);
+ return copied;
+
+out:
+ TCP_CHECK_TIMER(sk);
+ release_sock(sk);
+ return err;
+
+recv_urg:
+ err = tcp_recv_urg(sk, timeo, msg, len, flags, addr_len);
+ goto out;
+#else
+ return 0;
+#endif
+}
+
+/*
+ * State processing on a close. This implements the state shift for
+ * sending our FIN frame. Note that we only send a FIN for some
+ * states. A shutdown() may have already sent the FIN, or we may be
+ * closed.
+ */
+
+static unsigned char new_state[16] = {
+ /* current state: new state: action: */
+ /* (Invalid) */ TCP_CLOSE,
+ /* TCP_ESTABLISHED */ TCP_FIN_WAIT1 | TCP_ACTION_FIN,
+ /* TCP_SYN_SENT */ TCP_CLOSE,
+ /* TCP_SYN_RECV */ TCP_FIN_WAIT1 | TCP_ACTION_FIN,
+ /* TCP_FIN_WAIT1 */ TCP_FIN_WAIT1,
+ /* TCP_FIN_WAIT2 */ TCP_FIN_WAIT2,
+ /* TCP_TIME_WAIT */ TCP_CLOSE,
+ /* TCP_CLOSE */ TCP_CLOSE,
+ /* TCP_CLOSE_WAIT */ TCP_LAST_ACK | TCP_ACTION_FIN,
+ /* TCP_LAST_ACK */ TCP_LAST_ACK,
+ /* TCP_LISTEN */ TCP_CLOSE,
+ /* TCP_CLOSING */ TCP_CLOSING,
+};
+
+static int tcp_close_state(struct sock *sk)
+{
+#if 0
+ int next = (int) new_state[sk->state];
+ int ns = (next & TCP_STATE_MASK);
+
+ tcp_set_state(sk, ns);
+
+ return (next & TCP_ACTION_FIN);
+#else
+ return 0;
+#endif
+}
+
+/*
+ * Shutdown the sending side of a connection. Much like close except
+ * that we don't receive shut down or set sk->dead.
+ */
+
+void tcp_shutdown(struct sock *sk, int how)
+{
+#if 0
+ /* We need to grab some memory, and put together a FIN,
+ * and then put it into the queue to be sent.
+ * Tim MacKenzie(tym@dibbler.cs.monash.edu.au) 4 Dec '92.
+ */
+ if (!(how & SEND_SHUTDOWN))
+ return;
+
+ /* If we've already sent a FIN, or it's a closed state, skip this. */
+ if ((1 << sk->state) &
+ (TCPF_ESTABLISHED|TCPF_SYN_SENT|TCPF_SYN_RECV|TCPF_CLOSE_WAIT)) {
+ /* Clear out any half completed packets. FIN if needed. */
+ if (tcp_close_state(sk))
+ tcp_send_fin(sk);
+ }
+#endif
+}
+
+
+/*
+ * Return 1 if we still have things to send in our buffers.
+ */
+
+static inline int closing(struct sock * sk)
+{
+#if 0
+ return ((1 << sk->state) & (TCPF_FIN_WAIT1|TCPF_CLOSING|TCPF_LAST_ACK));
+#else
+ return 0;
+#endif
+}
+
+static __inline__ void tcp_kill_sk_queues(struct sock *sk)
+{
+#if 0
+ /* First the read buffer. */
+ __skb_queue_purge(&sk->receive_queue);
+
+ /* Next, the error queue. */
+ __skb_queue_purge(&sk->error_queue);
+
+ /* Next, the write queue. */
+ BUG_TRAP(skb_queue_empty(&sk->write_queue));
+
+ /* Account for returned memory. */
+ tcp_mem_reclaim(sk);
+
+ BUG_TRAP(sk->wmem_queued == 0);
+ BUG_TRAP(sk->forward_alloc == 0);
+
+ /* It is _impossible_ for the backlog to contain anything
+ * when we get here. All user references to this socket
+ * have gone away, only the net layer knows can touch it.
+ */
+#endif
+}
+
+/*
+ * At this point, there should be no process reference to this
+ * socket, and thus no user references at all. Therefore we
+ * can assume the socket waitqueue is inactive and nobody will
+ * try to jump onto it.
+ */
+void tcp_destroy_sock(struct sock *sk)
+{
+#if 0
+ BUG_TRAP(sk->state==TCP_CLOSE);
+ BUG_TRAP(sk->dead);
+
+ /* It cannot be in hash table! */
+ BUG_TRAP(sk->pprev==NULL);
+
+ /* If it has not 0 sk->num, it must be bound */
+ BUG_TRAP(!sk->num || sk->prev!=NULL);
+
+#ifdef TCP_DEBUG
+ if (sk->zapped) {
+ printk(KERN_DEBUG "TCP: double destroy sk=%p\n", sk);
+ sock_hold(sk);
+ }
+ sk->zapped = 1;
+#endif
+
+ sk->prot->destroy(sk);
+
+ tcp_kill_sk_queues(sk);
+
+#ifdef INET_REFCNT_DEBUG
+ if (atomic_read(&sk->refcnt) != 1) {
+ printk(KERN_DEBUG "Destruction TCP %p delayed, c=%d\n", sk, atomic_read(&sk->refcnt));
+ }
+#endif
+
+ atomic_dec(&tcp_orphan_count);
+ sock_put(sk);
+#endif
+}
+
+void tcp_close(struct sock *sk, long timeout)
+{
+#if 0
+ struct sk_buff *skb;
+ int data_was_unread = 0;
+
+ lock_sock(sk);
+ sk->shutdown = SHUTDOWN_MASK;
+
+ if(sk->state == TCP_LISTEN) {
+ tcp_set_state(sk, TCP_CLOSE);
+
+ /* Special case. */
+ tcp_listen_stop(sk);
+
+ goto adjudge_to_death;
+ }
+
+ /* We need to flush the recv. buffs. We do this only on the
+ * descriptor close, not protocol-sourced closes, because the
+ * reader process may not have drained the data yet!
+ */
+ while((skb=__skb_dequeue(&sk->receive_queue))!=NULL) {
+ u32 len = TCP_SKB_CB(skb)->end_seq - TCP_SKB_CB(skb)->seq - skb->h.th->fin;
+ data_was_unread += len;
+ __kfree_skb(skb);
+ }
+
+ tcp_mem_reclaim(sk);
+
+ /* As outlined in draft-ietf-tcpimpl-prob-03.txt, section
+ * 3.10, we send a RST here because data was lost. To
+ * witness the awful effects of the old behavior of always
+ * doing a FIN, run an older 2.1.x kernel or 2.0.x, start
+ * a bulk GET in an FTP client, suspend the process, wait
+ * for the client to advertise a zero window, then kill -9
+ * the FTP client, wheee... Note: timeout is always zero
+ * in such a case.
+ */
+ if(data_was_unread != 0) {
+ /* Unread data was tossed, zap the connection. */
+ NET_INC_STATS_USER(TCPAbortOnClose);
+ tcp_set_state(sk, TCP_CLOSE);
+ tcp_send_active_reset(sk, GFP_KERNEL);
+ } else if (sk->linger && sk->lingertime==0) {
+ /* Check zero linger _after_ checking for unread data. */
+ sk->prot->disconnect(sk, 0);
+ NET_INC_STATS_USER(TCPAbortOnData);
+ } else if (tcp_close_state(sk)) {
+ /* We FIN if the application ate all the data before
+ * zapping the connection.
+ */
+
+ /* RED-PEN. Formally speaking, we have broken TCP state
+ * machine. State transitions:
+ *
+ * TCP_ESTABLISHED -> TCP_FIN_WAIT1
+ * TCP_SYN_RECV -> TCP_FIN_WAIT1 (forget it, it's impossible)
+ * TCP_CLOSE_WAIT -> TCP_LAST_ACK
+ *
+ * are legal only when FIN has been sent (i.e. in window),
+ * rather than queued out of window. Purists blame.
+ *
+ * F.e. "RFC state" is ESTABLISHED,
+ * if Linux state is FIN-WAIT-1, but FIN is still not sent.
+ *
+ * The visible declinations are that sometimes
+ * we enter time-wait state, when it is not required really
+ * (harmless), do not send active resets, when they are
+ * required by specs (TCP_ESTABLISHED, TCP_CLOSE_WAIT, when
+ * they look as CLOSING or LAST_ACK for Linux)
+ * Probably, I missed some more holelets.
+ * --ANK
+ */
+ tcp_send_fin(sk);
+ }
+
+ if (timeout) {
+ struct task_struct *tsk = current;
+ DECLARE_WAITQUEUE(wait, current);
+
+ add_wait_queue(sk->sleep, &wait);
+
+ do {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (!closing(sk))
+ break;
+ release_sock(sk);
+ timeout = schedule_timeout(timeout);
+ lock_sock(sk);
+ } while (!signal_pending(tsk) && timeout);
+
+ tsk->state = TASK_RUNNING;
+ remove_wait_queue(sk->sleep, &wait);
+ }
+
+adjudge_to_death:
+ /* It is the last release_sock in its life. It will remove backlog. */
+ release_sock(sk);
+
+
+ /* Now socket is owned by kernel and we acquire BH lock
+ to finish close. No need to check for user refs.
+ */
+ local_bh_disable();
+ bh_lock_sock(sk);
+ BUG_TRAP(sk->lock.users==0);
+
+ sock_hold(sk);
+ sock_orphan(sk);
+
+ /* This is a (useful) BSD violating of the RFC. There is a
+ * problem with TCP as specified in that the other end could
+ * keep a socket open forever with no application left this end.
+ * We use a 3 minute timeout (about the same as BSD) then kill
+ * our end. If they send after that then tough - BUT: long enough
+ * that we won't make the old 4*rto = almost no time - whoops
+ * reset mistake.
+ *
+ * Nope, it was not mistake. It is really desired behaviour
+ * f.e. on http servers, when such sockets are useless, but
+ * consume significant resources. Let's do it with special
+ * linger2 option. --ANK
+ */
+
+ if (sk->state == TCP_FIN_WAIT2) {
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ if (tp->linger2 < 0) {
+ tcp_set_state(sk, TCP_CLOSE);
+ tcp_send_active_reset(sk, GFP_ATOMIC);
+ NET_INC_STATS_BH(TCPAbortOnLinger);
+ } else {
+ int tmo = tcp_fin_time(tp);
+
+ if (tmo > TCP_TIMEWAIT_LEN) {
+ tcp_reset_keepalive_timer(sk, tcp_fin_time(tp));
+ } else {
+ atomic_inc(&tcp_orphan_count);
+ tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
+ goto out;
+ }
+ }
+ }
+ if (sk->state != TCP_CLOSE) {
+ tcp_mem_reclaim(sk);
+ if (atomic_read(&tcp_orphan_count) > sysctl_tcp_max_orphans ||
+ (sk->wmem_queued > SOCK_MIN_SNDBUF &&
+ atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])) {
+ if (net_ratelimit())
+ printk(KERN_INFO "TCP: too many of orphaned sockets\n");
+ tcp_set_state(sk, TCP_CLOSE);
+ tcp_send_active_reset(sk, GFP_ATOMIC);
+ NET_INC_STATS_BH(TCPAbortOnMemory);
+ }
+ }
+ atomic_inc(&tcp_orphan_count);
+
+ if (sk->state == TCP_CLOSE)
+ tcp_destroy_sock(sk);
+ /* Otherwise, socket is reprieved until protocol close. */
+
+out:
+ bh_unlock_sock(sk);
+ local_bh_enable();
+ sock_put(sk);
+#endif
+}
+
+/* These states need RST on ABORT according to RFC793 */
+
+extern __inline__ int tcp_need_reset(int state)
+{
+#if 0
+ return ((1 << state) &
+ (TCPF_ESTABLISHED|TCPF_CLOSE_WAIT|TCPF_FIN_WAIT1|
+ TCPF_FIN_WAIT2|TCPF_SYN_RECV));
+#else
+ return 0;
+#endif
+}
+
+int tcp_disconnect(struct sock *sk, int flags)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ int old_state;
+ int err = 0;
+
+ old_state = sk->state;
+ if (old_state != TCP_CLOSE)
+ tcp_set_state(sk, TCP_CLOSE);
+
+ /* ABORT function of RFC793 */
+ if (old_state == TCP_LISTEN) {
+ tcp_listen_stop(sk);
+ } else if (tcp_need_reset(old_state) ||
+ (tp->snd_nxt != tp->write_seq &&
+ (1<<old_state)&(TCPF_CLOSING|TCPF_LAST_ACK))) {
+ /* The last check adjusts for discrepance of Linux wrt. RFC
+ * states
+ */
+ tcp_send_active_reset(sk, gfp_any());
+ sk->err = ECONNRESET;
+ } else if (old_state == TCP_SYN_SENT)
+ sk->err = ECONNRESET;
+
+ tcp_clear_xmit_timers(sk);
+ __skb_queue_purge(&sk->receive_queue);
+ tcp_writequeue_purge(sk);
+ __skb_queue_purge(&tp->out_of_order_queue);
+
+ sk->dport = 0;
+
+ if (!(sk->userlocks&SOCK_BINDADDR_LOCK)) {
+ sk->rcv_saddr = 0;
+ sk->saddr = 0;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ memset(&sk->net_pinfo.af_inet6.saddr, 0, 16);
+ memset(&sk->net_pinfo.af_inet6.rcv_saddr, 0, 16);
+#endif
+ }
+
+ sk->shutdown = 0;
+ sk->done = 0;
+ tp->srtt = 0;
+ if ((tp->write_seq += tp->max_window+2) == 0)
+ tp->write_seq = 1;
+ tp->backoff = 0;
+ tp->snd_cwnd = 2;
+ tp->probes_out = 0;
+ tp->packets_out = 0;
+ tp->snd_ssthresh = 0x7fffffff;
+ tp->snd_cwnd_cnt = 0;
+ tp->ca_state = TCP_CA_Open;
+ tcp_clear_retrans(tp);
+ tcp_delack_init(tp);
+ tp->send_head = NULL;
+ tp->saw_tstamp = 0;
+ tcp_sack_reset(tp);
+ __sk_dst_reset(sk);
+
+ BUG_TRAP(!sk->num || sk->prev);
+
+ sk->error_report(sk);
+ return err;
+#else
+ return 0;
+#endif
+}
+
+/*
+ * Wait for an incoming connection, avoid race
+ * conditions. This must be called with the socket locked.
+ */
+static int wait_for_connect(struct sock * sk, long timeo)
+{
+#if 0
+ DECLARE_WAITQUEUE(wait, current);
+ int err;
+
+ /*
+ * True wake-one mechanism for incoming connections: only
+ * one process gets woken up, not the 'whole herd'.
+ * Since we do not 'race & poll' for established sockets
+ * anymore, the common case will execute the loop only once.
+ *
+ * Subtle issue: "add_wait_queue_exclusive()" will be added
+ * after any current non-exclusive waiters, and we know that
+ * it will always _stay_ after any new non-exclusive waiters
+ * because all non-exclusive waiters are added at the
+ * beginning of the wait-queue. As such, it's ok to "drop"
+ * our exclusiveness temporarily when we get woken up without
+ * having to remove and re-insert us on the wait queue.
+ */
+ add_wait_queue_exclusive(sk->sleep, &wait);
+ for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
+ release_sock(sk);
+ if (sk->tp_pinfo.af_tcp.accept_queue == NULL)
+ timeo = schedule_timeout(timeo);
+ lock_sock(sk);
+ err = 0;
+ if (sk->tp_pinfo.af_tcp.accept_queue)
+ break;
+ err = -EINVAL;
+ if (sk->state != TCP_LISTEN)
+ break;
+ err = sock_intr_errno(timeo);
+ if (signal_pending(current))
+ break;
+ err = -EAGAIN;
+ if (!timeo)
+ break;
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(sk->sleep, &wait);
+ return err;
+#else
+ return 0;
+#endif
+}
+
+/*
+ * This will accept the next outstanding connection.
+ */
+
+struct sock *tcp_accept(struct sock *sk, int flags, int *err)
+{
+#if 0
+ struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+ struct open_request *req;
+ struct sock *newsk;
+ int error;
+
+ lock_sock(sk);
+
+ /* We need to make sure that this socket is listening,
+ * and that it has something pending.
+ */
+ error = -EINVAL;
+ if (sk->state != TCP_LISTEN)
+ goto out;
+
+ /* Find already established connection */
+ if (!tp->accept_queue) {
+ long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
+
+ /* If this is a non blocking socket don't sleep */
+ error = -EAGAIN;
+ if (!timeo)
+ goto out;
+
+ error = wait_for_connect(sk, timeo);
+ if (error)
+ goto out;
+ }
+
+ req = tp->accept_queue;
+ if ((tp->accept_queue = req->dl_next) == NULL)
+ tp->accept_queue_tail = NULL;
+
+ newsk = req->sk;
+ tcp_acceptq_removed(sk);
+ tcp_openreq_fastfree(req);
+ BUG_TRAP(newsk->state != TCP_SYN_RECV);
+ release_sock(sk);
+ return newsk;
+
+out:
+ release_sock(sk);
+ *err = error;
+ return NULL;
+#else
+ return NULL;
+#endif
+}
+
+/*
+ * Socket option code for TCP.
+ */
+
+int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval,
+ int optlen)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int val;
+ int err = 0;
+
+ if (level != SOL_TCP)
+ return tp->af_specific->setsockopt(sk, level, optname,
+ optval, optlen);
+
+ if(optlen<sizeof(int))
+ return -EINVAL;
+
+ if (get_user(val, (int *)optval))
+ return -EFAULT;
+
+ lock_sock(sk);
+
+ switch(optname) {
+ case TCP_MAXSEG:
+ /* values greater than interface MTU won't take effect. however at
+ * the point when this call is done we typically don't yet know
+ * which interface is going to be used
+ */
+ if(val < 8 || val > MAX_TCP_WINDOW) {
+ err = -EINVAL;
+ break;
+ }
+ tp->user_mss = val;
+ break;
+
+ case TCP_NODELAY:
+ /* You cannot try to use this and TCP_CORK in
+ * tandem, so let the user know.
+ */
+ if (tp->nonagle == 2) {
+ err = -EINVAL;
+ break;
+ }
+ tp->nonagle = (val == 0) ? 0 : 1;
+ if (val)
+ tcp_push_pending_frames(sk, tp);
+ break;
+
+ case TCP_CORK:
+ /* When set indicates to always queue non-full frames.
+ * Later the user clears this option and we transmit
+ * any pending partial frames in the queue. This is
+ * meant to be used alongside sendfile() to get properly
+ * filled frames when the user (for example) must write
+ * out headers with a write() call first and then use
+ * sendfile to send out the data parts.
+ *
+ * You cannot try to use TCP_NODELAY and this mechanism
+ * at the same time, so let the user know.
+ */
+ if (tp->nonagle == 1) {
+ err = -EINVAL;
+ break;
+ }
+ if (val != 0) {
+ tp->nonagle = 2;
+ } else {
+ tp->nonagle = 0;
+
+ tcp_push_pending_frames(sk, tp);
+ }
+ break;
+
+ case TCP_KEEPIDLE:
+ if (val < 1 || val > MAX_TCP_KEEPIDLE)
+ err = -EINVAL;
+ else {
+ tp->keepalive_time = val * HZ;
+ if (sk->keepopen && !((1<<sk->state)&(TCPF_CLOSE|TCPF_LISTEN))) {
+ __u32 elapsed = tcp_time_stamp - tp->rcv_tstamp;
+ if (tp->keepalive_time > elapsed)
+ elapsed = tp->keepalive_time - elapsed;
+ else
+ elapsed = 0;
+ tcp_reset_keepalive_timer(sk, elapsed);
+ }
+ }
+ break;
+ case TCP_KEEPINTVL:
+ if (val < 1 || val > MAX_TCP_KEEPINTVL)
+ err = -EINVAL;
+ else
+ tp->keepalive_intvl = val * HZ;
+ break;
+ case TCP_KEEPCNT:
+ if (val < 1 || val > MAX_TCP_KEEPCNT)
+ err = -EINVAL;
+ else
+ tp->keepalive_probes = val;
+ break;
+ case TCP_SYNCNT:
+ if (val < 1 || val > MAX_TCP_SYNCNT)
+ err = -EINVAL;
+ else
+ tp->syn_retries = val;
+ break;
+
+ case TCP_LINGER2:
+ if (val < 0)
+ tp->linger2 = -1;
+ else if (val > sysctl_tcp_fin_timeout/HZ)
+ tp->linger2 = 0;
+ else
+ tp->linger2 = val*HZ;
+ break;
+
+ case TCP_DEFER_ACCEPT:
+ tp->defer_accept = 0;
+ if (val > 0) {
+ /* Translate value in seconds to number of retransmits */
+ while (tp->defer_accept < 32 && val > ((TCP_TIMEOUT_INIT/HZ)<<tp->defer_accept))
+ tp->defer_accept++;
+ tp->defer_accept++;
+ }
+ break;
+
+ case TCP_WINDOW_CLAMP:
+ if (val==0) {
+ if (sk->state != TCP_CLOSE) {
+ err = -EINVAL;
+ break;
+ }
+ tp->window_clamp = 0;
+ } else {
+ tp->window_clamp = val<SOCK_MIN_RCVBUF/2 ?
+ SOCK_MIN_RCVBUF/2 : val;
+ }
+ break;
+
+ case TCP_QUICKACK:
+ if (!val) {
+ tp->ack.pingpong = 1;
+ } else {
+ tp->ack.pingpong = 0;
+ if ((1<<sk->state)&(TCPF_ESTABLISHED|TCPF_CLOSE_WAIT) &&
+ tcp_ack_scheduled(tp)) {
+ tp->ack.pending |= TCP_ACK_PUSHED;
+ cleanup_rbuf(sk, 1);
+ if (!(val & 1))
+ tp->ack.pingpong = 1;
+ }
+ }
+ break;
+
+ default:
+ err = -ENOPROTOOPT;
+ break;
+ };
+ release_sock(sk);
+ return err;
+#else
+ return 0;
+#endif
+}
+
+int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval,
+ int *optlen)
+{
+#if 0
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ int val, len;
+
+ if(level != SOL_TCP)
+ return tp->af_specific->getsockopt(sk, level, optname,
+ optval, optlen);
+
+ if(get_user(len,optlen))
+ return -EFAULT;
+
+ len = min_t(unsigned int, len, sizeof(int));
+
+ if(len < 0)
+ return -EINVAL;
+
+ switch(optname) {
+ case TCP_MAXSEG:
+ val = tp->mss_cache;
+ if (val == 0 && ((1<<sk->state)&(TCPF_CLOSE|TCPF_LISTEN)))
+ val = tp->user_mss;
+ break;
+ case TCP_NODELAY:
+ val = (tp->nonagle == 1);
+ break;
+ case TCP_CORK:
+ val = (tp->nonagle == 2);
+ break;
+ case TCP_KEEPIDLE:
+ val = (tp->keepalive_time ? : sysctl_tcp_keepalive_time)/HZ;
+ break;
+ case TCP_KEEPINTVL:
+ val = (tp->keepalive_intvl ? : sysctl_tcp_keepalive_intvl)/HZ;
+ break;
+ case TCP_KEEPCNT:
+ val = tp->keepalive_probes ? : sysctl_tcp_keepalive_probes;
+ break;
+ case TCP_SYNCNT:
+ val = tp->syn_retries ? : sysctl_tcp_syn_retries;
+ break;
+ case TCP_LINGER2:
+ val = tp->linger2;
+ if (val >= 0)
+ val = (val ? : sysctl_tcp_fin_timeout)/HZ;
+ break;
+ case TCP_DEFER_ACCEPT:
+ val = tp->defer_accept == 0 ? 0 : ((TCP_TIMEOUT_INIT/HZ)<<(tp->defer_accept-1));
+ break;
+ case TCP_WINDOW_CLAMP:
+ val = tp->window_clamp;
+ break;
+ case TCP_INFO:
+ {
+ struct tcp_info info;
+ u32 now = tcp_time_stamp;
+
+ if(get_user(len,optlen))
+ return -EFAULT;
+ info.tcpi_state = sk->state;
+ info.tcpi_ca_state = tp->ca_state;
+ info.tcpi_retransmits = tp->retransmits;
+ info.tcpi_probes = tp->probes_out;
+ info.tcpi_backoff = tp->backoff;
+ info.tcpi_options = 0;
+ if (tp->tstamp_ok)
+ info.tcpi_options |= TCPI_OPT_TIMESTAMPS;
+ if (tp->sack_ok)
+ info.tcpi_options |= TCPI_OPT_SACK;
+ if (tp->wscale_ok) {
+ info.tcpi_options |= TCPI_OPT_WSCALE;
+ info.tcpi_snd_wscale = tp->snd_wscale;
+ info.tcpi_rcv_wscale = tp->rcv_wscale;
+ } else {
+ info.tcpi_snd_wscale = 0;
+ info.tcpi_rcv_wscale = 0;
+ }
+ if (tp->ecn_flags&TCP_ECN_OK)
+ info.tcpi_options |= TCPI_OPT_ECN;
+
+ info.tcpi_rto = (1000000*tp->rto)/HZ;
+ info.tcpi_ato = (1000000*tp->ack.ato)/HZ;
+ info.tcpi_snd_mss = tp->mss_cache;
+ info.tcpi_rcv_mss = tp->ack.rcv_mss;
+
+ info.tcpi_unacked = tp->packets_out;
+ info.tcpi_sacked = tp->sacked_out;
+ info.tcpi_lost = tp->lost_out;
+ info.tcpi_retrans = tp->retrans_out;
+ info.tcpi_fackets = tp->fackets_out;
+
+ info.tcpi_last_data_sent = ((now - tp->lsndtime)*1000)/HZ;
+ info.tcpi_last_ack_sent = 0;
+ info.tcpi_last_data_recv = ((now - tp->ack.lrcvtime)*1000)/HZ;
+ info.tcpi_last_ack_recv = ((now - tp->rcv_tstamp)*1000)/HZ;
+
+ info.tcpi_pmtu = tp->pmtu_cookie;
+ info.tcpi_rcv_ssthresh = tp->rcv_ssthresh;
+ info.tcpi_rtt = ((1000000*tp->srtt)/HZ)>>3;
+ info.tcpi_rttvar = ((1000000*tp->mdev)/HZ)>>2;
+ info.tcpi_snd_ssthresh = tp->snd_ssthresh;
+ info.tcpi_snd_cwnd = tp->snd_cwnd;
+ info.tcpi_advmss = tp->advmss;
+ info.tcpi_reordering = tp->reordering;
+
+ len = min_t(unsigned int, len, sizeof(info));
+ if(put_user(len, optlen))
+ return -EFAULT;
+ if(copy_to_user(optval, &info,len))
+ return -EFAULT;
+ return 0;
+ }
+ case TCP_QUICKACK:
+ val = !tp->ack.pingpong;
+ break;
+ default:
+ return -ENOPROTOOPT;
+ };
+
+ if(put_user(len, optlen))
+ return -EFAULT;
+ if(copy_to_user(optval, &val,len))
+ return -EFAULT;
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+
+//extern void __skb_cb_too_small_for_tcp(int, int);
+//extern void tcpdiag_init(void);
+
+void /* __init */ tcp_init(void)
+{
+#if 0
+ struct sk_buff *skb = NULL;
+ unsigned long goal;
+ int order, i;
+
+ if(sizeof(struct tcp_skb_cb) > sizeof(skb->cb))
+ __skb_cb_too_small_for_tcp(sizeof(struct tcp_skb_cb),
+ sizeof(skb->cb));
+
+ tcp_openreq_cachep = kmem_cache_create("tcp_open_request",
+ sizeof(struct open_request),
+ 0, SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if(!tcp_openreq_cachep)
+ panic("tcp_init: Cannot alloc open_request cache.");
+
+ tcp_bucket_cachep = kmem_cache_create("tcp_bind_bucket",
+ sizeof(struct tcp_bind_bucket),
+ 0, SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if(!tcp_bucket_cachep)
+ panic("tcp_init: Cannot alloc tcp_bind_bucket cache.");
+
+ tcp_timewait_cachep = kmem_cache_create("tcp_tw_bucket",
+ sizeof(struct tcp_tw_bucket),
+ 0, SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if(!tcp_timewait_cachep)
+ panic("tcp_init: Cannot alloc tcp_tw_bucket cache.");
+
+ /* Size and allocate the main established and bind bucket
+ * hash tables.
+ *
+ * The methodology is similar to that of the buffer cache.
+ */
+ if (num_physpages >= (128 * 1024))
+ goal = num_physpages >> (21 - PAGE_SHIFT);
+ else
+ goal = num_physpages >> (23 - PAGE_SHIFT);
+
+ for(order = 0; (1UL << order) < goal; order++)
+ ;
+ do {
+ tcp_ehash_size = (1UL << order) * PAGE_SIZE /
+ sizeof(struct tcp_ehash_bucket);
+ tcp_ehash_size >>= 1;
+ while (tcp_ehash_size & (tcp_ehash_size-1))
+ tcp_ehash_size--;
+ tcp_ehash = (struct tcp_ehash_bucket *)
+ __get_free_pages(GFP_ATOMIC, order);
+ } while (tcp_ehash == NULL && --order > 0);
+
+ if (!tcp_ehash)
+ panic("Failed to allocate TCP established hash table\n");
+ for (i = 0; i < (tcp_ehash_size<<1); i++) {
+ tcp_ehash[i].lock = RW_LOCK_UNLOCKED;
+ tcp_ehash[i].chain = NULL;
+ }
+
+ do {
+ tcp_bhash_size = (1UL << order) * PAGE_SIZE /
+ sizeof(struct tcp_bind_hashbucket);
+ if ((tcp_bhash_size > (64 * 1024)) && order > 0)
+ continue;
+ tcp_bhash = (struct tcp_bind_hashbucket *)
+ __get_free_pages(GFP_ATOMIC, order);
+ } while (tcp_bhash == NULL && --order >= 0);
+
+ if (!tcp_bhash)
+ panic("Failed to allocate TCP bind hash table\n");
+ for (i = 0; i < tcp_bhash_size; i++) {
+ tcp_bhash[i].lock = SPIN_LOCK_UNLOCKED;
+ tcp_bhash[i].chain = NULL;
+ }
+
+ /* Try to be a bit smarter and adjust defaults depending
+ * on available memory.
+ */
+ if (order > 4) {
+ sysctl_local_port_range[0] = 32768;
+ sysctl_local_port_range[1] = 61000;
+ sysctl_tcp_max_tw_buckets = 180000;
+ sysctl_tcp_max_orphans = 4096<<(order-4);
+ sysctl_max_syn_backlog = 1024;
+ } else if (order < 3) {
+ sysctl_local_port_range[0] = 1024*(3-order);
+ sysctl_tcp_max_tw_buckets >>= (3-order);
+ sysctl_tcp_max_orphans >>= (3-order);
+ sysctl_max_syn_backlog = 128;
+ }
+ tcp_port_rover = sysctl_local_port_range[0] - 1;
+
+ sysctl_tcp_mem[0] = 768<<order;
+ sysctl_tcp_mem[1] = 1024<<order;
+ sysctl_tcp_mem[2] = 1536<<order;
+ if (sysctl_tcp_mem[2] - sysctl_tcp_mem[1] > 512)
+ sysctl_tcp_mem[1] = sysctl_tcp_mem[2] - 512;
+ if (sysctl_tcp_mem[1] - sysctl_tcp_mem[0] > 512)
+ sysctl_tcp_mem[0] = sysctl_tcp_mem[1] - 512;
+
+ if (order < 3) {
+ sysctl_tcp_wmem[2] = 64*1024;
+ sysctl_tcp_rmem[0] = PAGE_SIZE;
+ sysctl_tcp_rmem[1] = 43689;
+ sysctl_tcp_rmem[2] = 2*43689;
+ }
+
+ printk(KERN_INFO "TCP: Hash tables configured (established %d bind %d)\n",
+ tcp_ehash_size<<1, tcp_bhash_size);
+
+ tcpdiag_init();
+#endif
+}
--- /dev/null
+*.sym
+*.sys
+*.o
--- /dev/null
+#ifndef _BASETSD_H
+#define _BASETSD_H
+#if __GNUC__ >=3
+#pragma GCC system_header
+#endif
+
+#ifdef __GNUC__
+#ifndef __int64
+#define __int64 long long
+#endif
+#endif
+
+#if defined(_WIN64)
+#define __int3264 __int64
+#define ADDRESS_TAG_BIT 0x40000000000UI64
+#else /* !_WIN64 */
+#define __int3264 __int32
+#define ADDRESS_TAG_BIT 0x80000000UL
+#define HandleToUlong( h ) ((ULONG)(ULONG_PTR)(h) )
+#define HandleToLong( h ) ((LONG)(LONG_PTR) (h) )
+#define LongToHandle( h) ((HANDLE)(LONG_PTR) (h))
+#define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) )
+#define PtrToLong( p ) ((LONG)(LONG_PTR) (p) )
+#define PtrToUint( p ) ((UINT)(UINT_PTR) (p) )
+#define PtrToInt( p ) ((INT)(INT_PTR) (p) )
+#define PtrToUshort( p ) ((unsigned short)(ULONG_PTR)(p) )
+#define PtrToShort( p ) ((short)(LONG_PTR)(p) )
+#define IntToPtr( i ) ((VOID*)(INT_PTR)((int)i))
+#define UIntToPtr( ui ) ((VOID*)(UINT_PTR)((unsigned int)ui))
+#define LongToPtr( l ) ((VOID*)(LONG_PTR)((long)l))
+#define ULongToPtr( ul ) ((VOID*)(ULONG_PTR)((unsigned long)ul))
+#endif /* !_WIN64 */
+
+#define UlongToPtr(ul) ULongToPtr(ul)
+#define UintToPtr(ui) UIntToPtr(ui)
+#define MAXUINT_PTR (~((UINT_PTR)0))
+#define MAXINT_PTR ((INT_PTR)(MAXUINT_PTR >> 1))
+#define MININT_PTR (~MAXINT_PTR)
+#define MAXULONG_PTR (~((ULONG_PTR)0))
+#define MAXLONG_PTR ((LONG_PTR)(MAXULONG_PTR >> 1))
+#define MINLONG_PTR (~MAXLONG_PTR)
+#define MAXUHALF_PTR ((UHALF_PTR)~0)
+#define MAXHALF_PTR ((HALF_PTR)(MAXUHALF_PTR >> 1))
+#define MINHALF_PTR (~MAXHALF_PTR)
+
+#ifndef RC_INVOKED
+#ifdef __cplusplus
+extern "C" {
+#endif
+typedef int LONG32, *PLONG32;
+#ifndef XFree86Server
+typedef int INT32, *PINT32;
+#endif /* ndef XFree86Server */
+typedef unsigned int ULONG32, *PULONG32;
+typedef unsigned int DWORD32, *PDWORD32;
+typedef unsigned int UINT32, *PUINT32;
+
+#if defined(_WIN64)
+typedef __int64 INT_PTR, *PINT_PTR;
+typedef unsigned __int64 UINT_PTR, *PUINT_PTR;
+typedef __int64 LONG_PTR, *PLONG_PTR;
+typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
+typedef unsigned __int64 HANDLE_PTR;
+typedef unsigned int UHALF_PTR, *PUHALF_PTR;
+typedef int HALF_PTR, *PHALF_PTR;
+
+#if 0 /* TODO when WIN64 is here */
+inline unsigned long HandleToUlong(const void* h )
+ { return((unsigned long) h ); }
+inline long HandleToLong( const void* h )
+ { return((long) h ); }
+inline void* LongToHandle( const long h )
+ { return((void*) (INT_PTR) h ); }
+inline unsigned long PtrToUlong( const void* p)
+ { return((unsigned long) p ); }
+inline unsigned int PtrToUint( const void* p )
+ { return((unsigned int) p ); }
+inline unsigned short PtrToUshort( const void* p )
+ { return((unsigned short) p ); }
+inline long PtrToLong( const void* p )
+ { return((long) p ); }
+inline int PtrToInt( const void* p )
+ { return((int) p ); }
+inline short PtrToShort( const void* p )
+ { return((short) p ); }
+inline void* IntToPtr( const int i )
+ { return( (void*)(INT_PTR)i ); }
+inline void* UIntToPtr(const unsigned int ui)
+ { return( (void*)(UINT_PTR)ui ); }
+inline void* LongToPtr( const long l )
+ { return( (void*)(LONG_PTR)l ); }
+inline void* ULongToPtr( const unsigned long ul )
+ { return( (void*)(ULONG_PTR)ul ); }
+#endif /* 0_ */
+
+#else /* !_WIN64 */
+typedef int INT_PTR, *PINT_PTR;
+typedef unsigned int UINT_PTR, *PUINT_PTR;
+typedef long LONG_PTR, *PLONG_PTR;
+typedef unsigned long ULONG_PTR, *PULONG_PTR;
+typedef unsigned short UHALF_PTR, *PUHALF_PTR;
+typedef short HALF_PTR, *PHALF_PTR;
+typedef unsigned long HANDLE_PTR;
+#endif /* !_WIN64 */
+
+typedef ULONG_PTR SIZE_T, *PSIZE_T;
+typedef LONG_PTR SSIZE_T, *PSSIZE_T;
+typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;
+typedef __int64 LONG64, *PLONG64;
+typedef __int64 INT64, *PINT64;
+typedef unsigned __int64 ULONG64, *PULONG64;
+typedef unsigned __int64 DWORD64, *PDWORD64;
+typedef unsigned __int64 UINT64, *PUINT64;
+#ifdef __cplusplus
+}
+#endif
+#endif /* !RC_INVOKED */
+
+#endif /* _BASETSD_H */
--- /dev/null
+/*
+ * af_irda.h
+ *
+ * IrDa ports interface
+ *
+ * This file is part of the MinGW package.
+ *
+ * Contributors:
+ * Created by Robert Dickenson <robd@users.sourceforge.net>
+ *
+ * THIS SOFTWARE IS NOT COPYRIGHTED
+ *
+ * This source code is offered for use in the public domain. You may
+ * use, modify or distribute it freely.
+ *
+ * This code is distributed in the hope that it will be useful but
+ * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
+ * DISCLAMED. This includes but is not limited to warranties of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#ifndef __AF_IRDA_H
+#define __AF_IRDA_H
+
+#if __GNUC__ >=3
+#pragma GCC system_header
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#pragma pack(push,4)
+
+
+/* GUIDs */
+
+#ifdef DEFINE_GUID
+DEFINE_GUID(GUID_DEVINTERFACE_IRDAPORT,
+ 0x86e0d1e0L, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x74);
+DEFINE_GUID(GUID_DEVINTERFACE_IRDAENUM_BUS_ENUMERATOR,
+ 0x4D36E978L, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x19);
+#endif // DEFINE_GUID
+
+#define WINDOWS_AF_IRDA 26
+#define WINDOWS_PF_IRDA WINDOWS_AF_IRDA
+
+#ifndef AF_IRDA
+#define AF_IRDA WINDOWS_AF_IRDA
+#endif
+
+#define IRDA_PROTO_SOCK_STREAM 1
+#define PF_IRDA AF_IRDA
+#define SOL_IRLMP 0x00FF
+#define SIO_LAZY_DISCOVERY _IOR('t', 127, ULONG)
+
+
+#define IAS_MAX_USER_STRING 256
+#define IAS_MAX_OCTET_STRING 1024
+#define IAS_MAX_CLASSNAME 64
+#define IAS_MAX_ATTRIBNAME 256
+
+#define IAS_ATTRIB_NO_CLASS ((ULONG)0x10)
+#define IAS_ATTRIB_NO_ATTRIB ((ULONG)0x00)
+#define IAS_ATTRIB_INT ((ULONG)0x01)
+#define IAS_ATTRIB_OCTETSEQ ((ULONG)0x02)
+#define IAS_ATTRIB_STR ((ULONG)0x03)
+
+#define IRLMP_ENUMDEVICES ((ULONG)0x10)
+#define IRLMP_IAS_SET ((ULONG)0x11)
+#define IRLMP_IAS_QUERY ((ULONG)0x12)
+#define IRLMP_SEND_PDU_LEN ((ULONG)0x13)
+#define IRLMP_EXCLUSIVE_MODE ((ULONG)0x14)
+#define IRLMP_IRLPT_MODE ((ULONG)0x15)
+#define IRLMP_9WIRE_MODE ((ULONG)0x16)
+
+#if 0
+// Available/Used on Windows 98 only ???
+#define IRLMP_TINYTP_MODE ((ULONG)0x17)
+#define IRLMP_PARAMETERS ((ULONG)0x18)
+#define IRLMP_DISCOVERY_MODE ((ULONG)0x19)
+// Available/Used on Windows CE only ???
+#define IRLMP_SHARP_MODE ((ULONG)0x20)
+#endif
+
+enum {
+// First hint byte
+ LM_HB1_PnP = 0x01,
+ LM_HB1_PDA_Palmtop = 0x02,
+ LM_HB1_Computer = 0x04,
+ LM_HB1_Printer = 0x08,
+ LM_HB1_Modem = 0x10,
+ LM_HB1_Fax = 0x20,
+ LM_HB1_LANAccess = 0x40,
+// Second hint byte
+ LM_HB2_Telephony = 0x01,
+ LM_HB2_FileServer = 0x02,
+// Any hint byte
+ LM_HB_Extension = 0x80,
+};
+
+#define LmCharSetASCII 0x00
+#define LmCharSetISO_8859_1 0x01
+#define LmCharSetISO_8859_2 0x02
+#define LmCharSetISO_8859_3 0x03
+#define LmCharSetISO_8859_4 0x04
+#define LmCharSetISO_8859_5 0x05
+#define LmCharSetISO_8859_6 0x06
+#define LmCharSetISO_8859_7 0x07
+#define LmCharSetISO_8859_8 0x08
+#define LmCharSetISO_8859_9 0x09
+#define LmCharSetUNICODE 0xFF
+
+#define LM_BAUD_1200 1200
+#define LM_BAUD_2400 2400
+#define LM_BAUD_9600 9600
+#define LM_BAUD_19200 19200
+#define LM_BAUD_38400 38400
+#define LM_BAUD_57600 57600
+#define LM_BAUD_115200 115200
+#define LM_BAUD_576K 576000
+#define LM_BAUD_1152K 1152000
+#define LM_BAUD_4M 4000000
+
+#if 0 // Available/Used on Windows 98 only ???
+typedef ULONG LM_BAUD_RATE;
+typedef struct {
+ ULONG nTXDataBytes; // packet transmit receive bytes
+ ULONG nRXDataBytes; // packet maximum receive bytes
+ LM_BAUD_RATE nBaudRate; // link negotiated baud
+ ULONG thresholdTime; // milliseconds for threshold time
+ ULONG discTime; // milliseconds for disconnect time
+ USHORT nMSLinkTurn; // milliseconds for link turn around time
+ UCHAR nTXPackets; // transmit window packets
+ UCHAR nRXPackets; // receive window packets
+} LM_IRPARMS;
+typedef LM_IRPARMS *PLM_IRPARMS;
+#endif
+
+typedef struct _SOCKADDR_IRDA {
+ USHORT irdaAddressFamily;
+ UCHAR irdaDeviceID[4];
+ char irdaServiceName[25];
+} SOCKADDR_IRDA;
+
+typedef struct _WINDOWS_IRDA_DEVICE_INFO {
+ UCHAR irdaDeviceID[4];
+ char irdaDeviceName[22];
+ UCHAR irdaDeviceHints1;
+ UCHAR irdaDeviceHints2;
+ UCHAR irdaCharSet;
+} WINDOWS_IRDA_DEVICE_INFO;
+
+typedef struct _WINDOWS_IAS_SET {
+ char irdaClassName[IAS_MAX_CLASSNAME];
+ char irdaAttribName[IAS_MAX_ATTRIBNAME];
+ ULONG irdaAttribType;
+ union {
+ LONG irdaAttribInt;
+ struct {
+ USHORT Len;
+ UCHAR OctetSeq[IAS_MAX_OCTET_STRING];
+ } irdaAttribOctetSeq;
+ struct {
+ UCHAR Len;
+ UCHAR CharSet;
+ UCHAR UsrStr[IAS_MAX_USER_STRING];
+ } irdaAttribUsrStr;
+ } irdaAttribute;
+} WINDOWS_IAS_SET;
+
+typedef struct _WINDOWS_IAS_QUERY {
+ UCHAR irdaDeviceID[4];
+ char irdaClassName[IAS_MAX_CLASSNAME];
+ char irdaAttribName[IAS_MAX_ATTRIBNAME];
+ ULONG irdaAttribType;
+ union {
+ LONG irdaAttribInt;
+ struct {
+ ULONG Len;
+ UCHAR OctetSeq[IAS_MAX_OCTET_STRING];
+ } irdaAttribOctetSeq;
+ struct {
+ ULONG Len;
+ ULONG CharSet;
+ UCHAR UsrStr[IAS_MAX_USER_STRING];
+ } irdaAttribUsrStr;
+ } irdaAttribute;
+} WINDOWS_IAS_QUERY;
+
+typedef struct _WINDOWS_DEVICELIST {
+ ULONG numDevice;
+ WINDOWS_IRDA_DEVICE_INFO Device[1];
+} WINDOWS_DEVICELIST;
+
+typedef WINDOWS_DEVICELIST DEVICELIST;
+typedef WINDOWS_DEVICELIST *PDEVICELIST;
+typedef WINDOWS_DEVICELIST *PWINDOWS_DEVICELIST;
+
+typedef WINDOWS_IRDA_DEVICE_INFO IRDA_DEVICE_INFO;
+typedef WINDOWS_IRDA_DEVICE_INFO *PIRDA_DEVICE_INFO;
+typedef WINDOWS_IRDA_DEVICE_INFO *PWINDOWS_IRDA_DEVICE_INFO;
+
+typedef WINDOWS_IAS_SET IAS_SET;
+typedef WINDOWS_IAS_SET *PIAS_SET;
+typedef WINDOWS_IAS_SET *PWINDOWS_IAS_SET;
+
+typedef WINDOWS_IAS_QUERY IAS_QUERY;
+typedef WINDOWS_IAS_QUERY *PIAS_QUERY;
+typedef WINDOWS_IAS_QUERY *PWINDOWS_IAS_QUERY;
+
+typedef SOCKADDR_IRDA *PSOCKADDR_IRDA;
+
+#pragma pack(pop)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __AF_IRDA_H */
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: include/msvcrt/crttypes.h
+ * PURPOSE:
+ * PROGRAMMER:
+ * UPDATE HISTORY:
+ *
+ */
+
+#ifndef __CRT_TYPES__
+#define __CRT_TYPES__
+
+
+#ifdef __GNUC__
+
+//typedef long long LONGLONG;
+//typedef unsigned long long ULONGLONG;
+//typedef long long *PLONGLONG;
+//typedef unsigned long long *PULONGLONG;
+#define HAVE_LONGLONG
+#define LONGLONG_DEFINED
+#define LONGLONG long long
+#define ULONGLONG unsigned long long
+#define PLONGLONG long long *
+#define PULONGLONG unsigned long long *
+
+#else /*__GNUC__*/
+
+#define LONGLONG_DEFINED
+#define LONGLONG __int64
+#define ULONGLONG unsigned __int64
+#define PLONGLONG __int64*
+#define PULONGLONG unsigned __int64*
+#define __attribute__(a)
+#define __volatile
+
+#define inline __inline
+#define __asm__
+#define __volatile__(a)
+#define __attribute__(a)
+struct _KTHREAD { int foobar; };
+struct _ETHREAD { int foobar; };
+struct _EPROCESS { int foobar; };
+
+#ifndef _DEBUG
+#pragma function(_disable,_enable)
+#pragma function(_inp,_inpw,_outp,_outpw)
+#pragma function(_lrotl,_lrotr,_rotl,_rotr)
+#pragma function(abs,fabs,labs)
+#pragma function(memcpy,memcmp,memset)
+#pragma function(strcat,strcmp,strcpy,strlen,_strset)
+#pragma function(fmod,sqrt)
+#pragma function(log,log10,pow,exp)
+#pragma function(tan,atan,atan2,tanh)
+#pragma function(cos,acos,cosh)
+#pragma function(sin,asin,sinh)
+#endif
+
+#endif /*__GNUC__*/
+
+
+#endif /* __CRT_TYPES__ */
--- /dev/null
+/* $Id$ */
+
+#ifndef __INCLUDE_DDK_LDRTYPES_H
+#define __INCLUDE_DDK_LDRTYPES_H
+
+typedef struct _LDR_RESOURCE_INFO
+{
+ ULONG Type;
+ ULONG Name;
+ ULONG Language;
+} LDR_RESOURCE_INFO, *PLDR_RESOURCE_INFO;
+
+#define RESOURCE_TYPE_LEVEL 0
+#define RESOURCE_NAME_LEVEL 1
+#define RESOURCE_LANGUAGE_LEVEL 2
+#define RESOURCE_DATA_LEVEL 3
+
+#endif /* __INCLUDE_DDK_LDRTYPES_H */
--- /dev/null
+/* $Id$
+ *
+ */
+
+#ifndef __DDK_RTL_H
+#define __DDK_RTL_H
+
+#if defined(__NTOSKRNL__) || defined(__NTDRIVER__) || defined(__NTHAL__) || defined(__NTDLL__) || defined (__NTAPP__)
+
+#include <stddef.h>
+#include <stdarg.h>
+
+#endif /* __NTOSKRNL__ || __NTDRIVER__ || __NTHAL__ || __NTDLL__ || __NTAPP__ */
+
+#include <pe.h>
+
+
+#ifndef __USE_W32API
+
+/*
+ * PURPOSE: Flags for RtlQueryRegistryValues
+ */
+#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)
+
+/*
+ * VOID
+ * InitializeObjectAttributes (
+ * POBJECT_ATTRIBUTES InitializedAttributes,
+ * PUNICODE_STRING ObjectName,
+ * ULONG Attributes,
+ * HANDLE RootDirectory,
+ * PSECURITY_DESCRIPTOR SecurityDescriptor
+ * );
+ *
+ * FUNCTION: Sets up a parameter of type OBJECT_ATTRIBUTES for a
+ * subsequent call to ZwCreateXXX or ZwOpenXXX
+ * ARGUMENTS:
+ * InitializedAttributes (OUT) = Caller supplied storage for the
+ * object attributes
+ * ObjectName = Full path name for object
+ * Attributes = Attributes for the object
+ * RootDirectory = Where the object should be placed or NULL
+ * SecurityDescriptor = Ignored
+ */
+#define InitializeObjectAttributes(p,n,a,r,s) \
+{ \
+ (p)->Length = sizeof(OBJECT_ATTRIBUTES); \
+ (p)->ObjectName = n; \
+ (p)->Attributes = a; \
+ (p)->RootDirectory = r; \
+ (p)->SecurityDescriptor = s; \
+ (p)->SecurityQualityOfService = NULL; \
+}
+
+
+/*
+ * VOID
+ * InitializeListHead (
+ * PLIST_ENTRY ListHead
+ * );
+ *
+ * FUNCTION: Initializes a double linked list
+ * ARGUMENTS:
+ * ListHead = Caller supplied storage for the head of the list
+ */
+#define InitializeListHead(ListHead) \
+{ \
+ (ListHead)->Flink = (ListHead); \
+ (ListHead)->Blink = (ListHead); \
+}
+
+
+/*
+ * VOID
+ * InsertHeadList (
+ * PLIST_ENTRY ListHead,
+ * PLIST_ENTRY Entry
+ * );
+ *
+ * FUNCTION: Inserts an entry in a double linked list
+ * ARGUMENTS:
+ * ListHead = Head of the list
+ * Entry = Entry to insert
+ */
+#define InsertHeadList(ListHead, ListEntry) \
+{ \
+ PLIST_ENTRY OldFlink; \
+ OldFlink = (ListHead)->Flink; \
+ (ListEntry)->Flink = OldFlink; \
+ (ListEntry)->Blink = (ListHead); \
+ OldFlink->Blink = (ListEntry); \
+ (ListHead)->Flink = (ListEntry); \
+ assert((ListEntry) != NULL); \
+ assert((ListEntry)->Blink!=NULL); \
+ assert((ListEntry)->Blink->Flink == (ListEntry)); \
+ assert((ListEntry)->Flink != NULL); \
+ assert((ListEntry)->Flink->Blink == (ListEntry)); \
+}
+
+
+/*
+ * VOID
+ * InsertTailList (
+ * PLIST_ENTRY ListHead,
+ * PLIST_ENTRY Entry
+ * );
+ *
+ * FUNCTION:
+ * Inserts an entry in a double linked list
+ *
+ * ARGUMENTS:
+ * ListHead = Head of the list
+ * Entry = Entry to insert
+ */
+#define InsertTailList(ListHead, ListEntry) \
+{ \
+ PLIST_ENTRY OldBlink; \
+ OldBlink = (ListHead)->Blink; \
+ (ListEntry)->Flink = (ListHead); \
+ (ListEntry)->Blink = OldBlink; \
+ OldBlink->Flink = (ListEntry); \
+ (ListHead)->Blink = (ListEntry); \
+ assert((ListEntry) != NULL); \
+ assert((ListEntry)->Blink != NULL); \
+ assert((ListEntry)->Blink->Flink == (ListEntry)); \
+ assert((ListEntry)->Flink != NULL); \
+ assert((ListEntry)->Flink->Blink == (ListEntry)); \
+}
+
+/*
+ * BOOLEAN
+ * IsListEmpty (
+ * PLIST_ENTRY ListHead
+ * );
+ *
+ * FUNCTION:
+ * Checks if a double linked list is empty
+ *
+ * ARGUMENTS:
+ * ListHead = Head of the list
+*/
+#define IsListEmpty(ListHead) \
+ ((ListHead)->Flink == (ListHead))
+
+
+/*
+ * PSINGLE_LIST_ENTRY
+ * PopEntryList (
+ * PSINGLE_LIST_ENTRY ListHead
+ * );
+ *
+ * FUNCTION:
+ * Removes an entry from the head of a single linked list
+ *
+ * ARGUMENTS:
+ * ListHead = Head of the list
+ *
+ * RETURNS:
+ * The removed entry
+ */
+/*
+#define PopEntryList(ListHead) \
+ (ListHead)->Next; \
+ { \
+ PSINGLE_LIST_ENTRY FirstEntry; \
+ FirstEntry = (ListHead)->Next; \
+ if (FirstEntry != NULL) \
+ { \
+ (ListHead)->Next = FirstEntry->Next; \
+ } \
+ }
+*/
+static inline PSINGLE_LIST_ENTRY
+PopEntryList(PSINGLE_LIST_ENTRY ListHead)
+{
+ PSINGLE_LIST_ENTRY ListEntry;
+
+ ListEntry = ListHead->Next;
+ if (ListEntry!=NULL)
+ {
+ ListHead->Next = ListEntry->Next;
+ }
+
+ return(ListEntry);
+}
+
+#define RtlCopyMemory(Destination,Source,Length) \
+ memcpy((Destination),(Source),(Length))
+
+static
+inline
+VOID
+PushEntryList (
+ PSINGLE_LIST_ENTRY ListHead,
+ PSINGLE_LIST_ENTRY Entry
+ )
+{
+ Entry->Next = ListHead->Next;
+ ListHead->Next = Entry;
+}
+
+/*
+ *VOID
+ *RemoveEntryList (
+ * PLIST_ENTRY Entry
+ * );
+ *
+ * FUNCTION:
+ * Removes an entry from a double linked list
+ *
+ * ARGUMENTS:
+ * ListEntry = Entry to remove
+ */
+#define RemoveEntryList(ListEntry) \
+{ \
+ PLIST_ENTRY OldFlink; \
+ PLIST_ENTRY OldBlink; \
+ assert((ListEntry) != NULL); \
+ assert((ListEntry)->Blink!=NULL); \
+ assert((ListEntry)->Blink->Flink == (ListEntry)); \
+ assert((ListEntry)->Flink != NULL); \
+ assert((ListEntry)->Flink->Blink == (ListEntry)); \
+ OldFlink = (ListEntry)->Flink; \
+ OldBlink = (ListEntry)->Blink; \
+ OldFlink->Blink = OldBlink; \
+ OldBlink->Flink = OldFlink; \
+ (ListEntry)->Flink = NULL; \
+ (ListEntry)->Blink = NULL; \
+}
+
+
+/*
+ * PLIST_ENTRY
+ * RemoveHeadList (
+ * PLIST_ENTRY ListHead
+ * );
+ *
+ * FUNCTION:
+ * Removes the head entry from a double linked list
+ *
+ * ARGUMENTS:
+ * ListHead = Head of the list
+ *
+ * RETURNS:
+ * The removed entry
+ */
+/*
+#define RemoveHeadList(ListHead) \
+ (ListHead)->Flink; \
+ {RemoveEntryList((ListHead)->Flink)}
+*/
+/*
+PLIST_ENTRY
+RemoveHeadList (
+ PLIST_ENTRY ListHead
+ );
+*/
+
+static
+inline
+PLIST_ENTRY
+RemoveHeadList (
+ PLIST_ENTRY ListHead
+ )
+{
+ PLIST_ENTRY Old;
+ PLIST_ENTRY OldFlink;
+ PLIST_ENTRY OldBlink;
+
+ Old = ListHead->Flink;
+
+ OldFlink = ListHead->Flink->Flink;
+ OldBlink = ListHead->Flink->Blink;
+ OldFlink->Blink = OldBlink;
+ OldBlink->Flink = OldFlink;
+ if (Old != ListHead)
+ {
+ Old->Flink = NULL;
+ Old->Blink = NULL;
+ }
+
+ return(Old);
+}
+
+
+/*
+ * PLIST_ENTRY
+ * RemoveTailList (
+ * PLIST_ENTRY ListHead
+ * );
+ *
+ * FUNCTION:
+ * Removes the tail entry from a double linked list
+ *
+ * ARGUMENTS:
+ * ListHead = Head of the list
+ *
+ * RETURNS:
+ * The removed entry
+ */
+/*
+#define RemoveTailList(ListHead) \
+ (ListHead)->Blink; \
+ {RemoveEntryList((ListHead)->Blink)}
+*/
+/*
+PLIST_ENTRY
+RemoveTailList (
+ PLIST_ENTRY ListHead
+ );
+*/
+
+static
+inline
+PLIST_ENTRY
+RemoveTailList (
+ PLIST_ENTRY ListHead
+ )
+{
+ PLIST_ENTRY Old;
+ PLIST_ENTRY OldFlink;
+ PLIST_ENTRY OldBlink;
+
+ Old = ListHead->Blink;
+
+ OldFlink = ListHead->Blink->Flink;
+ OldBlink = ListHead->Blink->Blink;
+ OldFlink->Blink = OldBlink;
+ OldBlink->Flink = OldFlink;
+ if (Old != ListHead)
+ {
+ Old->Flink = NULL;
+ Old->Blink = NULL;
+ }
+
+ return(Old);
+}
+
+NTSTATUS
+STDCALL
+RtlAppendUnicodeToString (
+ PUNICODE_STRING Destination,
+ PWSTR Source
+ );
+
+ULONG
+STDCALL
+RtlCompareMemory (
+ PVOID Source1,
+ PVOID Source2,
+ ULONG Length
+ );
+
+BOOLEAN
+STDCALL
+RtlEqualUnicodeString (
+ PUNICODE_STRING String1,
+ PUNICODE_STRING String2,
+ BOOLEAN CaseInSensitive
+ );
+
+VOID
+RtlGetCallersAddress (
+ PVOID * CallersAddress
+ );
+
+NTSTATUS
+STDCALL
+RtlQueryRegistryValues (
+ IN ULONG RelativeTo,
+ IN PWSTR Path,
+ IN PRTL_QUERY_REGISTRY_TABLE QueryTable,
+ IN PVOID Context,
+ IN PVOID Environment
+ );
+
+NTSTATUS
+STDCALL
+RtlWriteRegistryValue (
+ ULONG RelativeTo,
+ PWSTR Path,
+ PWSTR ValueName,
+ ULONG ValueType,
+ PVOID ValueData,
+ ULONG ValueLength
+ );
+
+NTSTATUS STDCALL
+RtlDeleteRegistryValue(IN ULONG RelativeTo,
+ IN PWSTR Path,
+ IN PWSTR ValueName);
+
+VOID STDCALL
+RtlMoveMemory (PVOID Destination, CONST VOID* Source, ULONG Length);
+
+BOOLEAN STDCALL
+RtlEqualLuid(IN PLUID Luid1,
+ IN PLUID Luid2);
+
+VOID
+STDCALL
+RtlFillMemory (
+ PVOID Destination,
+ ULONG Length,
+ UCHAR Fill
+ );
+
+VOID STDCALL
+RtlZeroMemory (PVOID Destination, ULONG Length);
+
+#else /* __USE_W32API */
+
+#include <ddk/ntifs.h>
+
+#endif /* __USE_W32API */
+
+
+/*
+ * PURPOSE: Used with RtlCheckRegistryKey, RtlCreateRegistryKey,
+ * RtlDeleteRegistryKey
+ */
+#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_ENUM 6 // ReactOS specific: Used internally in kernel only
+#define RTL_REGISTRY_MAXIMUM 7
+
+#define RTL_REGISTRY_HANDLE 0x40000000
+#define RTL_REGISTRY_OPTIONAL 0x80000000
+
+
+#define SHORT_SIZE (sizeof(USHORT))
+#define SHORT_MASK (SHORT_SIZE-1)
+#define LONG_SIZE (sizeof(ULONG))
+#define LONG_MASK (LONG_SIZE-1)
+#define LOWBYTE_MASK 0x00FF
+
+#define FIRSTBYTE(Value) ((Value) & LOWBYTE_MASK)
+#define SECONDBYTE(Value) (((Value) >> 8) & LOWBYTE_MASK)
+#define THIRDBYTE(Value) (((Value) >> 16) & LOWBYTE_MASK)
+#define FOURTHBYTE(Value) (((Value) >> 24) & LOWBYTE_MASK)
+
+/* FIXME: reverse byte-order on big-endian machines (e.g. MIPS) */
+#define SHORT_LEAST_SIGNIFICANT_BIT 0
+#define SHORT_MOST_SIGNIFICANT_BIT 1
+
+#define LONG_LEAST_SIGNIFICANT_BIT 0
+#define LONG_3RD_MOST_SIGNIFICANT_BIT 1
+#define LONG_2RD_MOST_SIGNIFICANT_BIT 2
+#define LONG_MOST_SIGNIFICANT_BIT 3
+
+
+
+#if defined(__NTOSKRNL__) || defined(__NTDLL__)
+#define NLS_MB_CODE_PAGE_TAG NlsMbCodePageTag
+#define NLS_MB_OEM_CODE_PAGE_TAG NlsMbOemCodePageTag
+#else
+#define NLS_MB_CODE_PAGE_TAG (*NlsMbCodePageTag)
+#define NLS_MB_OEM_CODE_PAGE_TAG (*NlsMbOemCodePageTag)
+#endif /* __NTOSKRNL__ || __NTDLL__ */
+
+extern BOOLEAN NLS_MB_CODE_PAGE_TAG;
+extern BOOLEAN NLS_MB_OEM_CODE_PAGE_TAG;
+
+
+/*
+ * NOTE: ReactOS extensions
+ */
+#define RtlMin(X,Y) (((X) < (Y))? (X) : (Y))
+#define RtlMax(X,Y) (((X) > (Y))? (X) : (Y))
+#define RtlMin3(X,Y,Z) (((X) < (Y)) ? RtlMin(X,Z) : RtlMin(Y,Z))
+#define RtlMax3(X,Y,Z) (((X) > (Y)) ? RtlMax(X,Z) : RtlMax(Y,Z))
+
+
+/*
+ * VOID
+ * InitializeUnicodeString(PUNICODE_STRING DestinationString,
+ * USHORT Lenght,
+ * USHORT MaximumLength,
+ * PCWSTR Buffer);
+ *
+ * Initialize n UNICODE_STRING from its fields. Use when you know the values of
+ * all the fields in advance
+ */
+
+#define InitializeUnicodeString(__PDEST_STRING__,__LENGTH__,__MAXLENGTH__,__BUFFER__) \
+{ \
+ (__PDEST_STRING__)->Length = (__LENGTH__); \
+ (__PDEST_STRING__)->MaximumLength = (__MAXLENGTH__); \
+ (__PDEST_STRING__)->Buffer = (__BUFFER__); \
+}
+
+
+/*
+ * VOID
+ * RtlInitUnicodeStringFromLiteral(PUNICODE_STRING DestinationString,
+ * PCWSTR SourceString);
+ *
+ * Initialize a UNICODE_STRING from a wide string literal. WARNING: use only with
+ * string literals and statically initialized arrays, it will calculate the wrong
+ * length otherwise
+ */
+
+#define RtlInitUnicodeStringFromLiteral(__PDEST_STRING__,__SOURCE_STRING__) \
+ InitializeUnicodeString( \
+ (__PDEST_STRING__), \
+ sizeof(__SOURCE_STRING__) - sizeof(WCHAR), \
+ sizeof(__SOURCE_STRING__), \
+ (__SOURCE_STRING__) \
+)
+
+
+/*
+ * Static initializer for UNICODE_STRING variables.
+ *
+ * Usage:
+ * UNICODE_STRING wstr = UNICODE_STRING_INITIALIZER(L"string");
+ */
+
+#define UNICODE_STRING_INITIALIZER(__SOURCE_STRING__) \
+{ \
+ sizeof((__SOURCE_STRING__)) - sizeof(WCHAR), \
+ sizeof((__SOURCE_STRING__)), \
+ (__SOURCE_STRING__) \
+}
+
+
+/*
+ * Initializer for empty UNICODE_STRING variables.
+ *
+ * Usage:
+ * UNICODE_STRING wstr = EMPTY_UNICODE_STRING;
+ */
+
+#define EMPTY_UNICODE_STRING {0, 0, NULL}
+
+
+/*
+VOID
+PushEntryList (
+ PSINGLE_LIST_ENTRY ListHead,
+ PSINGLE_LIST_ENTRY Entry
+ );
+*/
+/*
+#define PushEntryList(ListHead,Entry) \
+ (Entry)->Next = (ListHead)->Next; \
+ (ListHead)->Next = (Entry)
+*/
+
+
+#ifndef __USE_W32API
+
+
+/*
+ * An ReactOS extension
+ */
+static
+inline
+PSINGLE_LIST_ENTRY
+ PopEntrySList(
+ PSLIST_HEADER ListHead
+ )
+{
+ PSINGLE_LIST_ENTRY ListEntry;
+
+ ListEntry = ListHead->s.Next.Next;
+ if (ListEntry!=NULL)
+ {
+ ListHead->s.Next.Next = ListEntry->Next;
+ ListHead->s.Depth++;
+ ListHead->s.Sequence++;
+ }
+ return ListEntry;
+}
+
+
+/*
+ * An ReactOS extension
+ */
+static
+inline
+VOID
+PushEntrySList (
+ PSLIST_HEADER ListHead,
+ PSINGLE_LIST_ENTRY Entry
+ )
+{
+ Entry->Next = ListHead->s.Next.Next;
+ ListHead->s.Next.Next = Entry;
+ ListHead->s.Depth++;
+ ListHead->s.Sequence++;
+}
+
+#else /* __USE_W32API */
+
+/*
+ * An ReactOS extension
+ */
+static
+inline
+PSINGLE_LIST_ENTRY
+ PopEntrySList(
+ PSLIST_HEADER ListHead
+ )
+{
+ PSINGLE_LIST_ENTRY ListEntry;
+
+ ListEntry = ListHead->Next.Next;
+ if (ListEntry!=NULL)
+ {
+ ListHead->Next.Next = ListEntry->Next;
+ ListHead->Depth++;
+ ListHead->Sequence++;
+ }
+ return ListEntry;
+}
+
+
+/*
+ * An ReactOS extension
+ */
+static
+inline
+VOID
+PushEntrySList (
+ PSLIST_HEADER ListHead,
+ PSINGLE_LIST_ENTRY Entry
+ )
+{
+ Entry->Next = ListHead->Next.Next;
+ ListHead->Next.Next = Entry;
+ ListHead->Depth++;
+ ListHead->Sequence++;
+}
+
+#endif /* __USE_W32API */
+
+
+NTSTATUS
+STDCALL
+RtlAddAtomToAtomTable (
+ IN PRTL_ATOM_TABLE AtomTable,
+ IN PWSTR AtomName,
+ OUT PRTL_ATOM Atom
+ );
+
+PVOID STDCALL
+RtlAllocateHeap (
+ HANDLE Heap,
+ ULONG Flags,
+ ULONG Size
+ );
+
+WCHAR
+STDCALL
+RtlAnsiCharToUnicodeChar (
+ CHAR AnsiChar
+ );
+
+ULONG
+STDCALL
+RtlAnsiStringToUnicodeSize (
+ PANSI_STRING AnsiString
+ );
+
+NTSTATUS
+STDCALL
+RtlAnsiStringToUnicodeString (
+ PUNICODE_STRING DestinationString,
+ PANSI_STRING SourceString,
+ BOOLEAN AllocateDestinationString
+ );
+
+NTSTATUS
+STDCALL
+RtlAppendAsciizToString(
+ PSTRING Destination,
+ PCSZ Source
+ );
+
+NTSTATUS
+STDCALL
+RtlAppendStringToString (
+ PSTRING Destination,
+ PSTRING Source
+ );
+
+NTSTATUS
+STDCALL
+RtlAppendUnicodeStringToString (
+ PUNICODE_STRING Destination,
+ PUNICODE_STRING Source
+ );
+
+BOOLEAN
+STDCALL
+RtlAreBitsClear (
+ PRTL_BITMAP BitMapHeader,
+ ULONG StartingIndex,
+ ULONG Length
+ );
+
+BOOLEAN
+STDCALL
+RtlAreBitsSet (
+ PRTL_BITMAP BitMapHeader,
+ ULONG StartingIndex,
+ ULONG Length
+ );
+
+VOID
+STDCALL
+RtlAssert (
+ PVOID FailedAssertion,
+ PVOID FileName,
+ ULONG LineNumber,
+ PCHAR Message
+ );
+
+NTSTATUS
+STDCALL
+RtlCharToInteger (
+ PCSZ String,
+ ULONG Base,
+ PULONG Value
+ );
+
+NTSTATUS
+STDCALL
+RtlCheckRegistryKey (
+ ULONG RelativeTo,
+ PWSTR Path
+ );
+
+VOID
+STDCALL
+RtlClearAllBits (
+ IN PRTL_BITMAP BitMapHeader
+ );
+
+VOID
+STDCALL
+RtlClearBits (
+ IN PRTL_BITMAP BitMapHeader,
+ IN ULONG StartingIndex,
+ IN ULONG NumberToClear
+ );
+
+DWORD
+STDCALL
+RtlCompactHeap (
+ HANDLE hheap,
+ DWORD flags
+ );
+
+LONG
+STDCALL
+RtlCompareString (
+ PSTRING String1,
+ PSTRING String2,
+ BOOLEAN CaseInsensitive
+ );
+
+LONG
+STDCALL
+RtlCompareUnicodeString (
+ PUNICODE_STRING String1,
+ PUNICODE_STRING String2,
+ BOOLEAN CaseInsensitive
+ );
+
+NTSTATUS STDCALL
+RtlCompressBuffer(IN USHORT CompressionFormatAndEngine,
+ IN PUCHAR UncompressedBuffer,
+ IN ULONG UncompressedBufferSize,
+ OUT PUCHAR CompressedBuffer,
+ IN ULONG CompressedBufferSize,
+ IN ULONG UncompressedChunkSize,
+ OUT PULONG FinalCompressedSize,
+ IN PVOID WorkSpace);
+
+NTSTATUS STDCALL
+RtlCompressChunks(IN PUCHAR UncompressedBuffer,
+ IN ULONG UncompressedBufferSize,
+ OUT PUCHAR CompressedBuffer,
+ IN ULONG CompressedBufferSize,
+ IN OUT PCOMPRESSED_DATA_INFO CompressedDataInfo,
+ IN ULONG CompressedDataInfoLength,
+ IN PVOID WorkSpace);
+
+LARGE_INTEGER STDCALL
+RtlConvertLongToLargeInteger(IN LONG SignedInteger);
+
+NTSTATUS STDCALL
+RtlConvertSidToUnicodeString(IN OUT PUNICODE_STRING String,
+ IN PSID Sid,
+ IN BOOLEAN AllocateString);
+
+LARGE_INTEGER STDCALL
+RtlConvertUlongToLargeInteger(IN ULONG UnsignedInteger);
+
+#if 0
+VOID
+RtlCopyBytes (
+ PVOID Destination,
+ CONST VOID * Source,
+ ULONG Length
+ );
+
+VOID
+RtlCopyMemory (
+ VOID * Destination,
+ CONST VOID * Source,
+ ULONG Length
+ );
+#endif
+
+#define RtlCopyBytes RtlCopyMemory
+
+VOID STDCALL
+RtlCopyLuid(IN PLUID LuidDest,
+ IN PLUID LuidSrc);
+
+VOID STDCALL
+RtlCopyLuidAndAttributesArray(ULONG Count,
+ PLUID_AND_ATTRIBUTES Src,
+ PLUID_AND_ATTRIBUTES Dest);
+
+NTSTATUS STDCALL
+RtlCopySid(ULONG BufferLength,
+ PSID Dest,
+ PSID Src);
+
+NTSTATUS STDCALL
+RtlCopySidAndAttributesArray(ULONG Count,
+ PSID_AND_ATTRIBUTES Src,
+ ULONG SidAreaSize,
+ PSID_AND_ATTRIBUTES Dest,
+ PVOID SidArea,
+ PVOID* RemainingSidArea,
+ PULONG RemainingSidAreaSize);
+
+VOID STDCALL
+RtlCopyString(PSTRING DestinationString,
+ PSTRING SourceString);
+
+VOID STDCALL
+RtlCopyUnicodeString(PUNICODE_STRING DestinationString,
+ PUNICODE_STRING SourceString);
+
+NTSTATUS STDCALL
+RtlCreateAtomTable(IN ULONG TableSize,
+ IN OUT PRTL_ATOM_TABLE *AtomTable);
+
+HANDLE
+STDCALL
+RtlCreateHeap (
+ ULONG Flags,
+ PVOID BaseAddress,
+ ULONG SizeToReserve, // dwMaximumSize
+ ULONG SizeToCommit, // dwInitialSize
+ PVOID Unknown,
+ PRTL_HEAP_DEFINITION Definition
+ );
+
+NTSTATUS
+STDCALL
+RtlCreateRegistryKey (
+ ULONG RelativeTo,
+ PWSTR Path
+ );
+
+NTSTATUS
+STDCALL
+RtlCreateSecurityDescriptor (
+ PSECURITY_DESCRIPTOR SecurityDescriptor,
+ ULONG Revision
+ );
+
+BOOLEAN
+STDCALL
+RtlCreateUnicodeString (
+ OUT PUNICODE_STRING Destination,
+ IN PWSTR Source
+ );
+
+BOOLEAN STDCALL
+RtlCreateUnicodeStringFromAsciiz (OUT PUNICODE_STRING Destination,
+ IN PCSZ Source);
+
+NTSTATUS
+STDCALL
+RtlCustomCPToUnicodeN (
+ PRTL_NLS_DATA NlsData,
+ PWCHAR UnicodeString,
+ ULONG UnicodeSize,
+ PULONG ResultSize,
+ PCHAR CustomString,
+ ULONG CustomSize
+ );
+
+NTSTATUS STDCALL
+RtlDecompressBuffer(IN USHORT CompressionFormat,
+ OUT PUCHAR UncompressedBuffer,
+ IN ULONG UncompressedBufferSize,
+ IN PUCHAR CompressedBuffer,
+ IN ULONG CompressedBufferSize,
+ OUT PULONG FinalUncompressedSize);
+
+NTSTATUS STDCALL
+RtlDecompressChunks(OUT PUCHAR UncompressedBuffer,
+ IN ULONG UncompressedBufferSize,
+ IN PUCHAR CompressedBuffer,
+ IN ULONG CompressedBufferSize,
+ IN PUCHAR CompressedTail,
+ IN ULONG CompressedTailSize,
+ IN PCOMPRESSED_DATA_INFO CompressedDataInfo);
+
+NTSTATUS STDCALL
+RtlDecompressFragment(IN USHORT CompressionFormat,
+ OUT PUCHAR UncompressedFragment,
+ IN ULONG UncompressedFragmentSize,
+ IN PUCHAR CompressedBuffer,
+ IN ULONG CompressedBufferSize,
+ IN ULONG FragmentOffset,
+ OUT PULONG FinalUncompressedSize,
+ IN PVOID WorkSpace);
+
+NTSTATUS STDCALL
+RtlDeleteAtomFromAtomTable(IN PRTL_ATOM_TABLE AtomTable,
+ IN RTL_ATOM Atom);
+
+NTSTATUS STDCALL
+RtlDescribeChunk(IN USHORT CompressionFormat,
+ IN OUT PUCHAR *CompressedBuffer,
+ IN PUCHAR EndOfCompressedBufferPlus1,
+ OUT PUCHAR *ChunkBuffer,
+ OUT PULONG ChunkSize);
+
+NTSTATUS STDCALL
+RtlDestroyAtomTable(IN PRTL_ATOM_TABLE AtomTable);
+
+BOOL STDCALL
+RtlDestroyHeap(HANDLE hheap);
+
+NTSTATUS
+STDCALL
+RtlDowncaseUnicodeString (
+ IN OUT PUNICODE_STRING DestinationString,
+ IN PUNICODE_STRING SourceString,
+ IN BOOLEAN AllocateDestinationString
+ );
+
+NTSTATUS
+STDCALL
+RtlEmptyAtomTable (
+ IN PRTL_ATOM_TABLE AtomTable,
+ IN BOOLEAN DeletePinned
+ );
+
+LARGE_INTEGER
+STDCALL
+RtlEnlargedIntegerMultiply (
+ LONG Multiplicand,
+ LONG Multiplier
+ );
+
+ULONG
+STDCALL
+RtlEnlargedUnsignedDivide (
+ ULARGE_INTEGER Dividend,
+ ULONG Divisor,
+ PULONG Remainder
+ );
+
+LARGE_INTEGER
+STDCALL
+RtlEnlargedUnsignedMultiply (
+ ULONG Multiplicand,
+ ULONG Multiplier
+ );
+
+BOOLEAN
+STDCALL
+RtlEqualString (
+ PSTRING String1,
+ PSTRING String2,
+ BOOLEAN CaseInSensitive
+ );
+
+LARGE_INTEGER
+STDCALL
+RtlExtendedIntegerMultiply (
+ LARGE_INTEGER Multiplicand,
+ LONG Multiplier
+ );
+
+LARGE_INTEGER
+STDCALL
+RtlExtendedLargeIntegerDivide (
+ LARGE_INTEGER Dividend,
+ ULONG Divisor,
+ PULONG Remainder
+ );
+
+LARGE_INTEGER
+STDCALL
+RtlExtendedMagicDivide (
+ LARGE_INTEGER Dividend,
+ LARGE_INTEGER MagicDivisor,
+ CCHAR ShiftCount
+ );
+
+VOID
+STDCALL
+RtlFillMemoryUlong (
+ PVOID Destination,
+ ULONG Length,
+ ULONG Fill
+ );
+
+ULONG
+STDCALL
+RtlFindClearBits (
+ PRTL_BITMAP BitMapHeader,
+ ULONG NumberToFind,
+ ULONG HintIndex
+ );
+
+ULONG
+STDCALL
+RtlFindClearBitsAndSet (
+ PRTL_BITMAP BitMapHeader,
+ ULONG NumberToFind,
+ ULONG HintIndex
+ );
+
+ULONG
+STDCALL
+RtlFindFirstRunClear (
+ PRTL_BITMAP BitMapHeader,
+ PULONG StartingIndex
+ );
+
+ULONG
+STDCALL
+RtlFindFirstRunSet (
+ PRTL_BITMAP BitMapHeader,
+ PULONG StartingIndex
+ );
+
+ULONG
+STDCALL
+RtlFindLongestRunClear (
+ PRTL_BITMAP BitMapHeader,
+ PULONG StartingIndex
+ );
+
+ULONG
+STDCALL
+RtlFindLongestRunSet (
+ PRTL_BITMAP BitMapHeader,
+ PULONG StartingIndex
+ );
+
+NTSTATUS
+STDCALL
+RtlFindMessage (
+ IN PVOID BaseAddress,
+ IN ULONG Type,
+ IN ULONG Language,
+ IN ULONG MessageId,
+ OUT PRTL_MESSAGE_RESOURCE_ENTRY *MessageResourceEntry
+ );
+
+ULONG
+STDCALL
+RtlFindSetBits (
+ PRTL_BITMAP BitMapHeader,
+ ULONG NumberToFind,
+ ULONG HintIndex
+ );
+
+ULONG
+STDCALL
+RtlFindSetBitsAndClear (
+ PRTL_BITMAP BitMapHeader,
+ ULONG NumberToFind,
+ ULONG HintIndex
+ );
+
+NTSTATUS
+STDCALL
+RtlFormatCurrentUserKeyPath (
+ IN OUT PUNICODE_STRING KeyPath
+ );
+
+VOID
+STDCALL
+RtlFreeAnsiString (
+ PANSI_STRING AnsiString
+ );
+
+BOOLEAN
+STDCALL
+RtlFreeHeap (
+ HANDLE Heap,
+ ULONG Flags,
+ PVOID Address
+ );
+
+VOID
+STDCALL
+RtlFreeOemString (
+ POEM_STRING OemString
+ );
+
+VOID
+STDCALL
+RtlFreeUnicodeString (
+ PUNICODE_STRING UnicodeString
+ );
+
+VOID STDCALL
+RtlGenerate8dot3Name(IN PUNICODE_STRING Name,
+ IN BOOLEAN AllowExtendedCharacters,
+ IN OUT PGENERATE_NAME_CONTEXT Context,
+ OUT PUNICODE_STRING Name8dot3);
+
+NTSTATUS STDCALL
+RtlGetCompressionWorkSpaceSize(IN USHORT CompressionFormatAndEngine,
+ OUT PULONG CompressBufferAndWorkSpaceSize,
+ OUT PULONG CompressFragmentWorkSpaceSize);
+
+VOID
+STDCALL
+RtlGetDefaultCodePage (
+ PUSHORT AnsiCodePage,
+ PUSHORT OemCodePage
+ );
+
+PVOID
+STDCALL
+RtlImageDirectoryEntryToData (
+ PVOID BaseAddress,
+ BOOLEAN bFlag,
+ ULONG Directory,
+ PULONG Size
+ );
+
+PIMAGE_NT_HEADERS
+STDCALL
+RtlImageNtHeader (
+ PVOID BaseAddress
+ );
+
+PIMAGE_SECTION_HEADER
+STDCALL
+RtlImageRvaToSection (
+ PIMAGE_NT_HEADERS NtHeader,
+ PVOID BaseAddress,
+ ULONG Rva
+ );
+
+ULONG
+STDCALL
+RtlImageRvaToVa (
+ PIMAGE_NT_HEADERS NtHeader,
+ PVOID BaseAddress,
+ ULONG Rva,
+ PIMAGE_SECTION_HEADER *SectionHeader
+ );
+
+VOID
+STDCALL
+RtlInitAnsiString (
+ PANSI_STRING DestinationString,
+ PCSZ SourceString
+ );
+
+VOID
+STDCALL
+RtlInitString (
+ PSTRING DestinationString,
+ PCSZ SourceString
+ );
+
+VOID
+STDCALL
+RtlInitUnicodeString (
+ PUNICODE_STRING DestinationString,
+ PCWSTR SourceString
+ );
+
+VOID
+STDCALL
+RtlInitializeBitMap (
+ IN OUT PRTL_BITMAP BitMapHeader,
+ IN PULONG BitMapBuffer,
+ IN ULONG SizeOfBitMap
+ );
+
+NTSTATUS
+STDCALL
+RtlInitializeContext (
+ IN HANDLE ProcessHandle,
+ IN PCONTEXT Context,
+ IN PVOID Parameter,
+ IN PTHREAD_START_ROUTINE StartAddress,
+ IN OUT PINITIAL_TEB InitialTeb
+ );
+
+VOID
+STDCALL
+RtlInitializeGenericTable (
+ IN OUT PRTL_GENERIC_TABLE Table,
+ IN PVOID CompareRoutine,
+ IN PVOID AllocateRoutine,
+ IN PVOID FreeRoutine,
+ IN ULONG UserParameter
+ );
+
+PVOID
+STDCALL
+RtlInsertElementGenericTable (
+ IN OUT PRTL_GENERIC_TABLE Table,
+ IN PVOID Element,
+ IN ULONG ElementSize,
+ IN ULONG Unknown4
+ );
+
+NTSTATUS
+STDCALL
+RtlIntegerToChar (
+ IN ULONG Value,
+ IN ULONG Base,
+ IN ULONG Length,
+ IN OUT PCHAR String
+ );
+
+NTSTATUS
+STDCALL
+RtlIntegerToUnicodeString (
+ IN ULONG Value,
+ IN ULONG Base,
+ IN OUT PUNICODE_STRING String
+ );
+
+BOOLEAN
+STDCALL
+RtlIsGenericTableEmpty (
+ IN PRTL_GENERIC_TABLE Table
+ );
+
+BOOLEAN STDCALL
+RtlIsNameLegalDOS8Dot3(IN PUNICODE_STRING UnicodeName,
+ IN PANSI_STRING AnsiName,
+ OUT PBOOLEAN SpacesFound);
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerAdd (
+ LARGE_INTEGER Addend1,
+ LARGE_INTEGER Addend2
+ );
+
+/*
+ * VOID
+ * RtlLargeIntegerAnd (
+ * PLARGE_INTEGER Result,
+ * LARGE_INTEGER Source,
+ * LARGE_INTEGER Mask
+ * );
+ */
+#define RtlLargeIntegerAnd(Result, Source, Mask) \
+{ \
+ Result.HighPart = Source.HighPart & Mask.HighPart; \
+ Result.LowPart = Source.LowPart & Mask.LowPart; \
+}
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerArithmeticShift (
+ LARGE_INTEGER LargeInteger,
+ CCHAR ShiftCount
+ );
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerDivide (
+ LARGE_INTEGER Dividend,
+ LARGE_INTEGER Divisor,
+ PLARGE_INTEGER Remainder
+ );
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerEqualTo (
+ * LARGE_INTEGER Operand1,
+ * LARGE_INTEGER Operand2
+ * );
+ */
+#define RtlLargeIntegerEqualTo(X,Y) \
+ (!(((X).LowPart ^ (Y).LowPart) | ((X).HighPart ^ (Y).HighPart)))
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerEqualToZero (
+ * LARGE_INTEGER Operand
+ * );
+ */
+#define RtlLargeIntegerEqualToZero(X) \
+ (!((X).LowPart | (X).HighPart))
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerGreaterThan (
+ * LARGE_INTEGER Operand1,
+ * LARGE_INTEGER Operand2
+ * );
+ */
+#define RtlLargeIntegerGreaterThan(X,Y) \
+ ((((X).HighPart == (Y).HighPart) && ((X).LowPart > (Y).LowPart)) || \
+ ((X).HighPart > (Y).HighPart))
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerGreaterThanOrEqualTo (
+ * LARGE_INTEGER Operand1,
+ * LARGE_INTEGER Operand2
+ * );
+ */
+#define RtlLargeIntegerGreaterThanOrEqualTo(X,Y) \
+ ((((X).HighPart == (Y).HighPart) && ((X).LowPart >= (Y).LowPart)) || \
+ ((X).HighPart > (Y).HighPart))
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerGreaterThanOrEqualToZero (
+ * LARGE_INTEGER Operand1
+ * );
+ */
+#define RtlLargeIntegerGreaterOrEqualToZero(X) \
+ ((X).HighPart >= 0)
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerGreaterThanZero (
+ * LARGE_INTEGER Operand1
+ * );
+ */
+#define RtlLargeIntegerGreaterThanZero(X) \
+ ((((X).HighPart == 0) && ((X).LowPart > 0)) || \
+ ((X).HighPart > 0 ))
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerLessThan (
+ * LARGE_INTEGER Operand1,
+ * LARGE_INTEGER Operand2
+ * );
+ */
+#define RtlLargeIntegerLessThan(X,Y) \
+ ((((X).HighPart == (Y).HighPart) && ((X).LowPart < (Y).LowPart)) || \
+ ((X).HighPart < (Y).HighPart))
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerLessThanOrEqualTo (
+ * LARGE_INTEGER Operand1,
+ * LARGE_INTEGER Operand2
+ * );
+ */
+#define RtlLargeIntegerLessThanOrEqualTo(X,Y) \
+ ((((X).HighPart == (Y).HighPart) && ((X).LowPart <= (Y).LowPart)) || \
+ ((X).HighPart < (Y).HighPart))
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerLessThanOrEqualToZero (
+ * LARGE_INTEGER Operand
+ * );
+ */
+#define RtlLargeIntegerLessOrEqualToZero(X) \
+ (((X).HighPart < 0) || !((X).LowPart | (X).HighPart))
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerLessThanZero (
+ * LARGE_INTEGER Operand
+ * );
+ */
+#define RtlLargeIntegerLessThanZero(X) \
+ (((X).HighPart < 0))
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerNegate (
+ LARGE_INTEGER Subtrahend
+ );
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerNotEqualTo (
+ * LARGE_INTEGER Operand1,
+ * LARGE_INTEGER Operand2
+ * );
+ */
+#define RtlLargeIntegerNotEqualTo(X,Y) \
+ ((((X).LowPart ^ (Y).LowPart) | ((X).HighPart ^ (Y).HighPart)))
+
+/*
+ * BOOLEAN
+ * RtlLargeIntegerNotEqualToZero (
+ * LARGE_INTEGER Operand
+ * );
+ */
+#define RtlLargeIntegerNotEqualToZero(X) \
+ (((X).LowPart | (X).HighPart))
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerShiftLeft (
+ LARGE_INTEGER LargeInteger,
+ CCHAR ShiftCount
+ );
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerShiftRight (
+ LARGE_INTEGER LargeInteger,
+ CCHAR ShiftCount
+ );
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerSubtract (
+ LARGE_INTEGER Minuend,
+ LARGE_INTEGER Subtrahend
+ );
+
+ULONG
+STDCALL
+RtlLengthSecurityDescriptor (
+ PSECURITY_DESCRIPTOR SecurityDescriptor
+ );
+
+BOOL
+STDCALL
+RtlLockHeap (
+ HANDLE hheap
+ );
+
+NTSTATUS
+STDCALL
+RtlLookupAtomInAtomTable (
+ IN PRTL_ATOM_TABLE AtomTable,
+ IN PWSTR AtomName,
+ OUT PRTL_ATOM Atom
+ );
+
+NTSTATUS
+STDCALL
+RtlMultiByteToUnicodeN (
+ PWCHAR UnicodeString,
+ ULONG UnicodeSize,
+ PULONG ResultSize,
+ PCHAR MbString,
+ ULONG MbSize
+ );
+
+NTSTATUS
+STDCALL
+RtlMultiByteToUnicodeSize (
+ PULONG UnicodeSize,
+ PCHAR MbString,
+ ULONG MbSize
+ );
+
+DWORD
+STDCALL
+RtlNtStatusToDosError (
+ NTSTATUS StatusCode
+ );
+
+DWORD
+STDCALL
+RtlNtStatusToDosErrorNoTeb (
+ NTSTATUS StatusCode
+ );
+
+int
+STDCALL
+RtlNtStatusToPsxErrno (
+ NTSTATUS StatusCode
+ );
+
+ULONG
+STDCALL
+RtlNumberGenericTableElements (
+ IN PRTL_GENERIC_TABLE Table
+ );
+
+ULONG
+STDCALL
+RtlNumberOfClearBits (
+ PRTL_BITMAP BitMapHeader
+ );
+
+ULONG
+STDCALL
+RtlNumberOfSetBits (
+ PRTL_BITMAP BitMapHeader
+ );
+
+ULONG
+STDCALL
+RtlOemStringToUnicodeSize (
+ POEM_STRING AnsiString
+ );
+
+NTSTATUS
+STDCALL
+RtlOemStringToUnicodeString (
+ PUNICODE_STRING DestinationString,
+ POEM_STRING SourceString,
+ BOOLEAN AllocateDestinationString
+ );
+
+NTSTATUS
+STDCALL
+RtlOemToUnicodeN (
+ PWCHAR UnicodeString,
+ ULONG UnicodeSize,
+ PULONG ResultSize,
+ PCHAR OemString,
+ ULONG OemSize
+ );
+
+NTSTATUS STDCALL
+RtlPinAtomInAtomTable (
+ IN PRTL_ATOM_TABLE AtomTable,
+ IN RTL_ATOM Atom
+ );
+
+BOOLEAN
+STDCALL
+RtlPrefixString (
+ PANSI_STRING String1,
+ PANSI_STRING String2,
+ BOOLEAN CaseInsensitive
+ );
+
+BOOLEAN
+STDCALL
+RtlPrefixUnicodeString (
+ PUNICODE_STRING String1,
+ PUNICODE_STRING String2,
+ BOOLEAN CaseInsensitive
+ );
+
+NTSTATUS
+STDCALL
+RtlQueryAtomInAtomTable (
+ IN PRTL_ATOM_TABLE AtomTable,
+ IN RTL_ATOM Atom,
+ IN OUT PULONG RefCount OPTIONAL,
+ IN OUT PULONG PinCount OPTIONAL,
+ IN OUT PWSTR AtomName OPTIONAL,
+ IN OUT PULONG NameLength OPTIONAL
+ );
+
+NTSTATUS
+STDCALL
+RtlQueryTimeZoneInformation (
+ IN OUT PTIME_ZONE_INFORMATION TimeZoneInformation
+ );
+
+VOID
+STDCALL
+RtlRaiseException (
+ IN PEXCEPTION_RECORD ExceptionRecord
+ );
+
+LPVOID
+STDCALL
+RtlReAllocateHeap (
+ HANDLE hheap,
+ DWORD flags,
+ LPVOID ptr,
+ DWORD size
+ );
+
+NTSTATUS STDCALL
+RtlReserveChunk(IN USHORT CompressionFormat,
+ IN OUT PUCHAR *CompressedBuffer,
+ IN PUCHAR EndOfCompressedBufferPlus1,
+ OUT PUCHAR *ChunkBuffer,
+ IN ULONG ChunkSize);
+
+/*
+ * VOID
+ * RtlRetrieveUlong (
+ * PULONG DestinationAddress,
+ * PULONG SourceAddress
+ * );
+ */
+#define RtlRetrieveUlong(DestAddress,SrcAddress) \
+ if ((ULONG)(SrcAddress) & LONG_MASK) \
+ { \
+ ((PUCHAR)(DestAddress))[0]=((PUCHAR)(SrcAddress))[0]; \
+ ((PUCHAR)(DestAddress))[1]=((PUCHAR)(SrcAddress))[1]; \
+ ((PUCHAR)(DestAddress))[2]=((PUCHAR)(SrcAddress))[2]; \
+ ((PUCHAR)(DestAddress))[3]=((PUCHAR)(SrcAddress))[3]; \
+ } \
+ else \
+ { \
+ *((PULONG)(DestAddress))=*((PULONG)(SrcAddress)); \
+ }
+
+/*
+ * VOID
+ * RtlRetrieveUshort (
+ * PUSHORT DestinationAddress,
+ * PUSHORT SourceAddress
+ * );
+ */
+#define RtlRetrieveUshort(DestAddress,SrcAddress) \
+ if ((ULONG)(SrcAddress) & SHORT_MASK) \
+ { \
+ ((PUCHAR)(DestAddress))[0]=((PUCHAR)(SrcAddress))[0]; \
+ ((PUCHAR)(DestAddress))[1]=((PUCHAR)(SrcAddress))[1]; \
+ } \
+ else \
+ { \
+ *((PUSHORT)(DestAddress))=*((PUSHORT)(SrcAddress)); \
+ }
+
+VOID
+STDCALL
+RtlSecondsSince1970ToTime (
+ ULONG SecondsSince1970,
+ PLARGE_INTEGER Time
+ );
+
+VOID
+STDCALL
+RtlSecondsSince1980ToTime (
+ ULONG SecondsSince1980,
+ PLARGE_INTEGER Time
+ );
+
+VOID
+STDCALL
+RtlSetAllBits (
+ IN PRTL_BITMAP BitMapHeader
+ );
+
+VOID
+STDCALL
+RtlSetBits (
+ PRTL_BITMAP BitMapHeader,
+ ULONG StartingIndex,
+ ULONG NumberToSet
+ );
+
+NTSTATUS
+STDCALL
+RtlSetDaclSecurityDescriptor (
+ PSECURITY_DESCRIPTOR SecurityDescriptor,
+ BOOLEAN DaclPresent,
+ PACL Dacl,
+ BOOLEAN DaclDefaulted
+ );
+
+NTSTATUS
+STDCALL
+RtlSetTimeZoneInformation (
+ IN OUT PTIME_ZONE_INFORMATION TimeZoneInformation
+ );
+
+DWORD
+STDCALL
+RtlSizeHeap (
+ HANDLE hheap,
+ DWORD flags,
+ PVOID pmem
+ );
+
+/*
+ * VOID
+ * RtlStoreUlong (
+ * PULONG Address,
+ * ULONG Value
+ * );
+ */
+#define RtlStoreUlong(Address,Value) \
+ if ((ULONG)(Address) & LONG_MASK) \
+ { \
+ ((PUCHAR)(Address))[LONG_LEAST_SIGNIFICANT_BIT]=(UCHAR)(FIRSTBYTE(Value)); \
+ ((PUCHAR)(Address))[LONG_3RD_MOST_SIGNIFICANT_BIT]=(UCHAR)(FIRSTBYTE(Value)); \
+ ((PUCHAR)(Address))[LONG_2ND_MOST_SIGNIFICANT_BIT]=(UCHAR)(THIRDBYTE(Value)); \
+ ((PUCHAR)(Address))[LONG_MOST_SIGNIFICANT_BIT]=(UCHAR)(FOURTHBYTE(Value)); \
+ } \
+ else \
+ { \
+ *((PULONG)(Address))=(ULONG)(Value); \
+ }
+
+/*
+ * VOID
+ * RtlStoreUshort (
+ * PUSHORT Address,
+ * USHORT Value
+ * );
+ */
+#define RtlStoreUshort(Address,Value) \
+ if ((ULONG)(Address) & SHORT_MASK) \
+ { \
+ ((PUCHAR)(Address))[SHORT_LEAST_SIGNIFICANT_BIT]=(UCHAR)(FIRSTBYTE(Value)); \
+ ((PUCHAR)(Address))[SHORT_MOST_SIGNIFICANT_BIT]=(UCHAR)(SECONDBYTE(Value)); \
+ } \
+ else \
+ { \
+ *((PUSHORT)(Address))=(USHORT)(Value); \
+ }
+
+BOOLEAN
+STDCALL
+RtlTimeFieldsToTime (
+ PTIME_FIELDS TimeFields,
+ PLARGE_INTEGER Time
+ );
+
+BOOLEAN
+STDCALL
+RtlTimeToSecondsSince1970 (
+ PLARGE_INTEGER Time,
+ PULONG SecondsSince1970
+ );
+
+BOOLEAN
+STDCALL
+RtlTimeToSecondsSince1980 (
+ PLARGE_INTEGER Time,
+ PULONG SecondsSince1980
+ );
+
+VOID
+STDCALL
+RtlTimeToTimeFields (
+ PLARGE_INTEGER Time,
+ PTIME_FIELDS TimeFields
+ );
+
+ULONG
+STDCALL
+RtlUnicodeStringToAnsiSize (
+ IN PUNICODE_STRING UnicodeString
+ );
+
+NTSTATUS
+STDCALL
+RtlUnicodeStringToAnsiString (
+ IN OUT PANSI_STRING DestinationString,
+ IN PUNICODE_STRING SourceString,
+ IN BOOLEAN AllocateDestinationString
+ );
+
+NTSTATUS
+STDCALL
+RtlUnicodeStringToInteger (
+ IN PUNICODE_STRING String,
+ IN ULONG Base,
+ OUT PULONG Value
+ );
+
+ULONG
+STDCALL
+RtlUnicodeStringToOemSize (
+ IN PUNICODE_STRING UnicodeString
+ );
+
+NTSTATUS
+STDCALL
+RtlUnicodeStringToCountedOemString (
+ IN OUT POEM_STRING DestinationString,
+ IN PUNICODE_STRING SourceString,
+ IN BOOLEAN AllocateDestinationString
+ );
+
+NTSTATUS
+STDCALL
+RtlUnicodeStringToOemString (
+ IN OUT POEM_STRING DestinationString,
+ IN PUNICODE_STRING SourceString,
+ IN BOOLEAN AllocateDestinationString
+ );
+
+NTSTATUS
+STDCALL
+RtlUnicodeToCustomCPN (
+ PRTL_NLS_DATA NlsData,
+ PCHAR MbString,
+ ULONG MbSize,
+ PULONG ResultSize,
+ PWCHAR UnicodeString,
+ ULONG UnicodeSize
+ );
+
+NTSTATUS
+STDCALL
+RtlUnicodeToMultiByteN (
+ PCHAR MbString,
+ ULONG MbSize,
+ PULONG ResultSize,
+ PWCHAR UnicodeString,
+ ULONG UnicodeSize
+ );
+
+NTSTATUS
+STDCALL
+RtlUnicodeToMultiByteSize (
+ PULONG MbSize,
+ PWCHAR UnicodeString,
+ ULONG UnicodeSize
+ );
+
+NTSTATUS
+STDCALL
+RtlUnicodeToOemN (
+ PCHAR OemString,
+ ULONG OemSize,
+ PULONG ResultSize,
+ PWCHAR UnicodeString,
+ ULONG UnicodeSize
+ );
+
+BOOL
+STDCALL
+RtlUnlockHeap (
+ HANDLE hheap
+ );
+
+VOID
+STDCALL
+RtlUnwind (
+ PEXCEPTION_REGISTRATION RegistrationFrame,
+ PVOID ReturnAddress,
+ PEXCEPTION_RECORD ExceptionRecord,
+ DWORD EaxValue
+ );
+
+WCHAR
+STDCALL
+RtlUpcaseUnicodeChar (
+ WCHAR Source
+ );
+
+NTSTATUS
+STDCALL
+RtlUpcaseUnicodeString (
+ IN OUT PUNICODE_STRING DestinationString,
+ IN PUNICODE_STRING SourceString,
+ IN BOOLEAN AllocateDestinationString
+ );
+
+NTSTATUS
+STDCALL
+RtlUpcaseUnicodeStringToAnsiString (
+ IN OUT PANSI_STRING DestinationString,
+ IN PUNICODE_STRING SourceString,
+ IN BOOLEAN AllocateDestinationString
+ );
+
+NTSTATUS
+STDCALL
+RtlUpcaseUnicodeStringToCountedOemString (
+ IN OUT POEM_STRING DestinationString,
+ IN PUNICODE_STRING SourceString,
+ IN BOOLEAN AllocateDestinationString
+ );
+
+NTSTATUS
+STDCALL
+RtlUpcaseUnicodeStringToOemString (
+ IN OUT POEM_STRING DestinationString,
+ IN PUNICODE_STRING SourceString,
+ IN BOOLEAN AllocateDestinationString
+ );
+
+NTSTATUS
+STDCALL
+RtlUpcaseUnicodeToCustomCPN (
+ PRTL_NLS_DATA NlsData,
+ PCHAR MbString,
+ ULONG MbSize,
+ PULONG ResultSize,
+ PWCHAR UnicodeString,
+ ULONG UnicodeSize
+ );
+
+NTSTATUS
+STDCALL
+RtlUpcaseUnicodeToMultiByteN (
+ PCHAR MbString,
+ ULONG MbSize,
+ PULONG ResultSize,
+ PWCHAR UnicodeString,
+ ULONG UnicodeSize
+ );
+
+NTSTATUS
+STDCALL
+RtlUpcaseUnicodeToOemN (
+ PCHAR OemString,
+ ULONG OemSize,
+ PULONG ResultSize,
+ PWCHAR UnicodeString,
+ ULONG UnicodeSize
+ );
+
+CHAR
+STDCALL
+RtlUpperChar (
+ CHAR Source
+ );
+
+VOID
+STDCALL
+RtlUpperString (
+ PSTRING DestinationString,
+ PSTRING SourceString
+ );
+
+BOOL
+STDCALL
+RtlValidateHeap (
+ HANDLE hheap,
+ DWORD flags,
+ PVOID pmem
+ );
+
+BOOLEAN
+STDCALL
+RtlValidSecurityDescriptor (
+ PSECURITY_DESCRIPTOR SecurityDescriptor
+ );
+
+BOOLEAN STDCALL
+RtlValidSid(IN PSID Sid);
+
+ULONG
+STDCALL
+RtlxAnsiStringToUnicodeSize (
+ IN PANSI_STRING AnsiString
+ );
+
+ULONG
+STDCALL
+RtlxOemStringToUnicodeSize (
+ IN POEM_STRING OemString
+ );
+
+ULONG
+STDCALL
+RtlxUnicodeStringToAnsiSize (
+ IN PUNICODE_STRING UnicodeString
+ );
+
+ULONG
+STDCALL
+RtlxUnicodeStringToOemSize (
+ IN PUNICODE_STRING UnicodeString
+ );
+
+
+/* Register io functions */
+
+UCHAR
+STDCALL
+READ_REGISTER_UCHAR (
+ PUCHAR Register
+ );
+
+USHORT
+STDCALL
+READ_REGISTER_USHORT (
+ PUSHORT Register
+ );
+
+ULONG
+STDCALL
+READ_REGISTER_ULONG (
+ PULONG Register
+ );
+
+VOID
+STDCALL
+READ_REGISTER_BUFFER_UCHAR (
+ PUCHAR Register,
+ PUCHAR Buffer,
+ ULONG Count
+ );
+
+VOID
+STDCALL
+READ_REGISTER_BUFFER_USHORT (
+ PUSHORT Register,
+ PUSHORT Buffer,
+ ULONG Count
+ );
+
+VOID
+STDCALL
+READ_REGISTER_BUFFER_ULONG (
+ PULONG Register,
+ PULONG Buffer,
+ ULONG Count
+ );
+
+VOID
+STDCALL
+WRITE_REGISTER_UCHAR (
+ PUCHAR Register,
+ UCHAR Value
+ );
+
+VOID
+STDCALL
+WRITE_REGISTER_USHORT (
+ PUSHORT Register,
+ USHORT Value
+ );
+
+VOID
+STDCALL
+WRITE_REGISTER_ULONG (
+ PULONG Register,
+ ULONG Value
+ );
+
+VOID
+STDCALL
+WRITE_REGISTER_BUFFER_UCHAR (
+ PUCHAR Register,
+ PUCHAR Buffer,
+ ULONG Count
+ );
+
+VOID
+STDCALL
+WRITE_REGISTER_BUFFER_USHORT (
+ PUSHORT Register,
+ PUSHORT Buffer,
+ ULONG Count
+ );
+
+VOID
+STDCALL
+WRITE_REGISTER_BUFFER_ULONG (
+ PULONG Register,
+ PULONG Buffer,
+ ULONG Count
+ );
+
+
+NTSTATUS STDCALL RtlCreateAcl(PACL Acl, ULONG AclSize, ULONG AclRevision);
+NTSTATUS STDCALL RtlQueryInformationAcl (PACL Acl, PVOID Information, ULONG InformationLength, ACL_INFORMATION_CLASS InformationClass);
+NTSTATUS STDCALL RtlSetInformationAcl (PACL Acl, PVOID Information, ULONG InformationLength, ACL_INFORMATION_CLASS InformationClass);
+BOOLEAN STDCALL RtlValidAcl (PACL Acl);
+
+NTSTATUS STDCALL RtlAddAccessAllowedAce(PACL Acl, ULONG Revision, ACCESS_MASK AccessMask, PSID Sid);
+NTSTATUS STDCALL RtlAddAccessDeniedAce(PACL Acl, ULONG Revision, ACCESS_MASK AccessMask, PSID Sid);
+NTSTATUS STDCALL RtlAddAce(PACL Acl, ULONG Revision, ULONG StartingIndex, PACE AceList, ULONG AceListLength);
+NTSTATUS STDCALL RtlAddAuditAccessAce (PACL Acl, ULONG Revision, ACCESS_MASK AccessMask, PSID Sid, BOOLEAN Success, BOOLEAN Failure);
+NTSTATUS STDCALL RtlDeleteAce(PACL Acl, ULONG AceIndex);
+BOOLEAN STDCALL RtlFirstFreeAce(PACL Acl, PACE* Ace);
+NTSTATUS STDCALL RtlGetAce(PACL Acl, ULONG AceIndex, PACE *Ace);
+
+NTSTATUS STDCALL RtlAbsoluteToSelfRelativeSD (PSECURITY_DESCRIPTOR AbsSD, PSECURITY_DESCRIPTOR RelSD, PULONG BufferLength);
+NTSTATUS STDCALL RtlMakeSelfRelativeSD (PSECURITY_DESCRIPTOR AbsSD, PSECURITY_DESCRIPTOR RelSD, PULONG BufferLength);
+NTSTATUS STDCALL RtlCreateSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG Revision);
+BOOLEAN STDCALL RtlValidSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor);
+ULONG STDCALL RtlLengthSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor);
+NTSTATUS STDCALL RtlSetDaclSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, BOOLEAN DaclPresent, PACL Dacl, BOOLEAN DaclDefaulted);
+NTSTATUS STDCALL RtlGetDaclSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PBOOLEAN DaclPresent, PACL* Dacl, PBOOLEAN DaclDefauted);
+NTSTATUS STDCALL RtlSetOwnerSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PSID Owner, BOOLEAN OwnerDefaulted);
+NTSTATUS STDCALL RtlGetOwnerSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PSID* Owner, PBOOLEAN OwnerDefaulted);
+NTSTATUS STDCALL RtlSetGroupSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PSID Group, BOOLEAN GroupDefaulted);
+NTSTATUS STDCALL RtlGetGroupSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PSID* Group, PBOOLEAN GroupDefaulted);
+NTSTATUS STDCALL RtlGetControlSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PSECURITY_DESCRIPTOR_CONTROL Control, PULONG Revision);
+NTSTATUS STDCALL RtlSetSaclSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, BOOLEAN SaclPresent, PACL Sacl, BOOLEAN SaclDefaulted);
+NTSTATUS STDCALL RtlGetSaclSecurityDescriptor (PSECURITY_DESCRIPTOR SecurityDescriptor, PBOOLEAN SaclPresent, PACL* Sacl, PBOOLEAN SaclDefauted);
+NTSTATUS STDCALL RtlSelfRelativeToAbsoluteSD (PSECURITY_DESCRIPTOR RelSD,
+ PSECURITY_DESCRIPTOR AbsSD,
+ PDWORD AbsSDSize,
+ PACL Dacl,
+ PDWORD DaclSize,
+ PACL Sacl,
+ PDWORD SaclSize,
+ PSID Owner,
+ PDWORD OwnerSize,
+ PSID Group,
+ PDWORD GroupSize);
+
+NTSTATUS STDCALL RtlAllocateAndInitializeSid (PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
+ UCHAR SubAuthorityCount,
+ ULONG SubAuthority0,
+ ULONG SubAuthority1,
+ ULONG SubAuthority2,
+ ULONG SubAuthority3,
+ ULONG SubAuthority4,
+ ULONG SubAuthority5,
+ ULONG SubAuthority6,
+ ULONG SubAuthority7,
+ PSID *Sid);
+ULONG STDCALL RtlLengthRequiredSid (UCHAR SubAuthorityCount);
+PSID_IDENTIFIER_AUTHORITY STDCALL RtlIdentifierAuthoritySid (PSID Sid);
+NTSTATUS STDCALL RtlInitializeSid (PSID Sid, PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, UCHAR SubAuthorityCount);
+PULONG STDCALL RtlSubAuthoritySid (PSID Sid, ULONG SubAuthority);
+BOOLEAN STDCALL RtlEqualPrefixSid (PSID Sid1, PSID Sid2);
+BOOLEAN STDCALL RtlEqualSid(PSID Sid1, PSID Sid2);
+PSID STDCALL RtlFreeSid (PSID Sid);
+ULONG STDCALL RtlLengthSid (PSID Sid);
+PULONG STDCALL RtlSubAuthoritySid (PSID Sid, ULONG SubAuthority);
+PUCHAR STDCALL RtlSubAuthorityCountSid (PSID Sid);
+BOOLEAN STDCALL RtlValidSid (PSID Sid);
+NTSTATUS STDCALL RtlConvertSidToUnicodeString (PUNICODE_STRING String, PSID Sid, BOOLEAN AllocateBuffer);
+
+BOOLEAN STDCALL RtlAreAllAccessesGranted (ACCESS_MASK GrantedAccess, ACCESS_MASK DesiredAccess);
+BOOLEAN STDCALL RtlAreAnyAccessesGranted (ACCESS_MASK GrantedAccess, ACCESS_MASK DesiredAccess);
+VOID STDCALL RtlMapGenericMask (PACCESS_MASK AccessMask, PGENERIC_MAPPING GenericMapping);
+
+
+/* functions exported from NTOSKRNL.EXE which are considered RTL */
+
+#if defined(__NTOSKRNL__) || defined(__NTDRIVER__) || defined(__NTHAL__) || defined(__NTDLL__) || defined(__NTAPP__)
+
+char *_itoa (int value, char *string, int radix);
+int _snprintf(char * buf, size_t cnt, const char *fmt, ...);
+int _snwprintf(wchar_t *buf, size_t cnt, const wchar_t *fmt, ...);
+int _stricmp(const char *s1, const char *s2);
+char * _strlwr(char *x);
+int _strnicmp(const char *s1, const char *s2, size_t n);
+char * _strnset(char* szToFill, int szFill, size_t sizeMaxFill);
+char * _strrev(char *s);
+char * _strset(char* szToFill, int szFill);
+char * _strupr(char *x);
+int _vsnprintf(char *buf, size_t cnt, const char *fmt, va_list args);
+int _wcsicmp (const wchar_t* cs, const wchar_t* ct);
+wchar_t * _wcslwr (wchar_t *x);
+int _wcsnicmp (const wchar_t * cs,const wchar_t * ct,size_t count);
+wchar_t* _wcsnset (wchar_t* wsToFill, wchar_t wcFill, size_t sizeMaxFill);
+wchar_t * _wcsrev(wchar_t *s);
+wchar_t *_wcsupr(wchar_t *x);
+
+int atoi(const char *str);
+long atol(const char *str);
+int isdigit(int c);
+int islower(int c);
+int isprint(int c);
+int isspace(int c);
+int isupper(int c);
+int isxdigit(int c);
+size_t mbstowcs (wchar_t *wcstr, const char *mbstr, size_t count);
+int mbtowc (wchar_t *wchar, const char *mbchar, size_t count);
+void * memchr(const void *s, int c, size_t n);
+void * memcpy(void *to, const void *from, size_t count);
+void * memmove(void *dest,const void *src, size_t count);
+void * memset(void *src, int val, size_t count);
+
+#if 0
+qsort
+#endif
+
+int rand(void);
+int sprintf(char * buf, const char *fmt, ...);
+void srand(unsigned seed);
+char * strcat(char *s, const char *append);
+char * strchr(const char *s, int c);
+int strcmp(const char *s1, const char *s2);
+char * strcpy(char *to, const char *from);
+size_t strlen(const char *str);
+char * strncat(char *dst, const char *src, size_t n);
+int strncmp(const char *s1, const char *s2, size_t n);
+char *strncpy(char *dst, const char *src, size_t n);
+char *strrchr(const char *s, int c);
+size_t strspn(const char *s1, const char *s2);
+char *strstr(const char *s, const char *find);
+int swprintf(wchar_t *buf, const wchar_t *fmt, ...);
+int tolower(int c);
+int toupper(int c);
+wchar_t towlower(wchar_t c);
+wchar_t towupper(wchar_t c);
+int vsprintf(char *buf, const char *fmt, va_list args);
+wchar_t * wcscat(wchar_t *dest, const wchar_t *src);
+wchar_t * wcschr(const wchar_t *str, wchar_t ch);
+int wcscmp(const wchar_t *cs, const wchar_t *ct);
+wchar_t* wcscpy(wchar_t* str1, const wchar_t* str2);
+size_t wcscspn(const wchar_t *str,const wchar_t *reject);
+size_t wcslen(const wchar_t *s);
+wchar_t * wcsncat(wchar_t *dest, const wchar_t *src, size_t count);
+int wcsncmp(const wchar_t *cs, const wchar_t *ct, size_t count);
+wchar_t * wcsncpy(wchar_t *dest, const wchar_t *src, size_t count);
+wchar_t * wcsrchr(const wchar_t *str, wchar_t ch);
+size_t wcsspn(const wchar_t *str,const wchar_t *accept);
+wchar_t *wcsstr(const wchar_t *s,const wchar_t *b);
+size_t wcstombs (char *mbstr, const wchar_t *wcstr, size_t count);
+int wctomb (char *mbchar, wchar_t wchar);
+
+#endif /* __NTOSKRNL__ || __NTDRIVER__ || __NTHAL__ || __NTDLL__ || __NTAPP__ */
+
+#endif /* __DDK_RTL_H */
--- /dev/null
+/* $Id$
+ *
+ */
+
+#ifndef __DDK_RTLTYPES_H
+#define __DDK_RTLTYPES_H
+
+#ifndef __USE_W32API
+
+#define COMPRESSION_FORMAT_NONE 0x0000
+#define COMPRESSION_FORMAT_DEFAULT 0x0001
+#define COMPRESSION_FORMAT_LZNT1 0x0002
+
+#define COMPRESSION_ENGINE_STANDARD 0x0000
+#define COMPRESSION_ENGINE_MAXIMUM 0x0100
+#define COMPRESSION_ENGINE_HIBER 0x0200
+
+typedef struct _CONTROLLER_OBJECT
+{
+ CSHORT Type;
+ CSHORT Size;
+ PVOID ControllerExtension;
+ KDEVICE_QUEUE DeviceWaitQueue;
+ ULONG Spare1;
+ LARGE_INTEGER Spare2;
+} CONTROLLER_OBJECT, *PCONTROLLER_OBJECT;
+
+typedef struct _STRING
+{
+ /*
+ * Length in bytes of the string stored in buffer
+ */
+ USHORT Length;
+
+ /*
+ * Maximum length of the string
+ */
+ USHORT MaximumLength;
+
+ /*
+ * String
+ */
+ PCHAR Buffer;
+} STRING, *PSTRING;
+
+typedef STRING ANSI_STRING;
+typedef PSTRING PANSI_STRING;
+
+typedef STRING OEM_STRING;
+typedef PSTRING POEM_STRING;
+
+typedef struct _TIME_FIELDS
+{
+ CSHORT Year;
+ CSHORT Month;
+ CSHORT Day;
+ CSHORT Hour;
+ CSHORT Minute;
+ CSHORT Second;
+ CSHORT Milliseconds;
+ CSHORT Weekday;
+} TIME_FIELDS, *PTIME_FIELDS;
+
+typedef struct _RTL_BITMAP
+{
+ ULONG SizeOfBitMap;
+ PULONG Buffer;
+} RTL_BITMAP, *PRTL_BITMAP;
+
+
+#ifdef __GNUC__
+#define STDCALL_FUNC STDCALL
+#else
+#define STDCALL_FUNC(a) (__stdcall a )
+#endif /*__GNUC__*/
+
+
+typedef NTSTATUS STDCALL_FUNC
+(*PRTL_QUERY_REGISTRY_ROUTINE) (PWSTR 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;
+
+typedef struct _COMPRESSED_DATA_INFO
+{
+ USHORT CompressionFormatAndEngine;
+ UCHAR CompressionUnitShift;
+ UCHAR ChunkShift;
+ UCHAR ClusterShift;
+ UCHAR Reserved;
+ USHORT NumberOfChunks;
+ ULONG CompressedChunkSizes[1];
+} COMPRESSED_DATA_INFO, *PCOMPRESSED_DATA_INFO;
+
+typedef struct _GENERATE_NAME_CONTEXT
+{
+ USHORT Checksum;
+ BOOLEAN CheckSumInserted;
+ UCHAR NameLength;
+ WCHAR NameBuffer[8];
+ ULONG ExtensionLength;
+ WCHAR ExtensionBuffer[4];
+ ULONG LastIndexValue;
+} GENERATE_NAME_CONTEXT, *PGENERATE_NAME_CONTEXT;
+
+typedef struct _RTL_SPLAY_LINKS
+{
+ struct _RTL_SPLAY_LINKS *Parent;
+ struct _RTL_SPLAY_LINKS *LeftChild;
+ struct _RTL_SPLAY_LINKS *RightChild;
+} RTL_SPLAY_LINKS, *PRTL_SPLAY_LINKS;
+
+#else /* __USE_W32API */
+
+#include <ddk/ntifs.h>
+
+#endif /* __USE_W32API */
+
+typedef struct _INITIAL_TEB
+{
+ ULONG StackCommit;
+ ULONG StackReserve;
+ PVOID StackBase;
+ PVOID StackLimit;
+ PVOID StackAllocate;
+} INITIAL_TEB, *PINITIAL_TEB;
+
+typedef struct _RTL_HEAP_DEFINITION
+{
+ ULONG Length;
+ ULONG Unknown[11];
+} RTL_HEAP_DEFINITION, *PRTL_HEAP_DEFINITION;
+
+typedef struct _RTL_ATOM_TABLE
+{
+ ULONG TableSize;
+ ULONG NumberOfAtoms;
+ PVOID Lock; /* fast mutex (kernel mode)/ critical section (user mode) */
+ PVOID HandleTable;
+ LIST_ENTRY Slot[0];
+} RTL_ATOM_TABLE, *PRTL_ATOM_TABLE;
+
+typedef struct _LB_RANGE
+{
+ UCHAR upper;
+ UCHAR lower;
+} LB_RANGE;
+
+typedef struct _RTL_NLS_DATA
+{
+ USHORT CodePage;
+ USHORT MaxCharacterSize; // SBCS = 1, DBCS = 2
+ WCHAR DefaultCharacter;
+ WCHAR char1;
+ WCHAR char2;
+ WCHAR char3;
+ USHORT DbcsFlag;
+ LB_RANGE LeadByteRange[6];
+ USHORT reserved;
+ PWCHAR MultiByteToUnicode;
+ PCHAR UnicodeToMultiByte;
+ PWCHAR DosMultiByteToUnicode;
+ PCHAR DbcsTags;
+} RTL_NLS_DATA, *PRTL_NLS_DATA;
+
+typedef struct _RTL_NLS_TABLE
+{
+ RTL_NLS_DATA OemInfo;
+ RTL_NLS_DATA AnsiInfo;
+ PWCHAR UpcaseTable;
+ PWCHAR DowncaseTable;
+} RTL_NLS_TABLE, *PRTL_NLS_TABLE;
+
+
+typedef struct _RTL_GENERIC_TABLE
+{
+ PVOID RootElement;
+ ULONG Unknown2;
+ ULONG Unknown3;
+ ULONG Unknown4;
+ ULONG Unknown5;
+ ULONG ElementCount;
+ PVOID CompareRoutine;
+ PVOID AllocateRoutine;
+ PVOID FreeRoutine;
+ ULONG UserParameter;
+} RTL_GENERIC_TABLE, *PRTL_GENERIC_TABLE;
+
+
+typedef struct _RTL_MESSAGE_RESOURCE_ENTRY
+{
+ USHORT Length;
+ USHORT Flags;
+ UCHAR Text[1];
+} RTL_MESSAGE_RESOURCE_ENTRY, *PRTL_MESSAGE_RESOURCE_ENTRY;
+
+typedef struct _RTL_MESSAGE_RESOURCE_BLOCK
+{
+ ULONG LowId;
+ ULONG HighId;
+ ULONG OffsetToEntries;
+} RTL_MESSAGE_RESOURCE_BLOCK, *PRTL_MESSAGE_RESOURCE_BLOCK;
+
+typedef struct _RTL_MESSAGE_RESOURCE_DATA
+{
+ ULONG NumberOfBlocks;
+ RTL_MESSAGE_RESOURCE_BLOCK Blocks[1];
+} RTL_MESSAGE_RESOURCE_DATA, *PRTL_MESSAGE_RESOURCE_DATA;
+
+#endif /* __DDK_RTLTYPES_H */
--- /dev/null
+
+/* $Id$
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: System call definitions
+ * FILE: include/ddk/zw.h
+ * REVISION HISTORY:
+ * ??/??/??: First few functions (David Welch)
+ * ??/??/??: Complete implementation by Ariadne
+ * 13/07/98: Reorganised things a bit (David Welch)
+ * 04/08/98: Added some documentation (Ariadne)
+ * 14/08/98: Added type TIME and change variable type from [1] to [0]
+ * 14/09/98: Added for each Nt call a corresponding Zw Call
+ */
+
+#ifndef __DDK_ZW_H
+#define __DDK_ZW_H
+
+#include <ntos/security.h>
+#include <ntos/zwtypes.h>
+#include <napi/npipe.h>
+
+#ifndef _RTLGETPROCESSHEAP_DEFINED_
+#define _RTLGETPROCESSHEAP_DEFINED_
+#define RtlGetProcessHeap() (NtCurrentPeb()->ProcessHeap)
+#endif
+
+// semaphore information
+
+typedef enum _SEMAPHORE_INFORMATION_CLASS
+{
+ SemaphoreBasicInformation = 0
+} SEMAPHORE_INFORMATION_CLASS;
+
+typedef struct _SEMAPHORE_BASIC_INFORMATION
+{
+ LONG CurrentCount;
+ LONG MaximumCount;
+} SEMAPHORE_BASIC_INFORMATION, *PSEMAPHORE_BASIC_INFORMATION;
+
+// event information
+
+typedef enum _EVENT_INFORMATION_CLASS
+{
+ EventBasicInformation = 0
+} EVENT_INFORMATION_CLASS;
+
+typedef struct _EVENT_BASIC_INFORMATION
+{
+ EVENT_TYPE EventType;
+ LONG EventState;
+} EVENT_BASIC_INFORMATION, *PEVENT_BASIC_INFORMATION;
+
+//#define LCID ULONG
+//#define SECURITY_INFORMATION ULONG
+//typedef ULONG SECURITY_INFORMATION;
+
+/*
+ * FUNCTION: Adjusts the groups in an access token
+ * ARGUMENTS:
+ * TokenHandle = Specifies the access token
+ * ResetToDefault = If true the NewState parameter is ignored and the groups are set to
+ * their default state, if false the groups specified in
+ * NewState are set.
+ * NewState =
+ * BufferLength = Specifies the size of the buffer for the PreviousState.
+ * PreviousState =
+ * ReturnLength = Bytes written in PreviousState buffer.
+ * REMARKS: The arguments map to the win32 AdjustTokenGroups
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtAdjustGroupsToken(
+ IN HANDLE TokenHandle,
+ IN BOOLEAN ResetToDefault,
+ IN PTOKEN_GROUPS NewState,
+ IN ULONG BufferLength,
+ OUT PTOKEN_GROUPS PreviousState OPTIONAL,
+ OUT PULONG ReturnLength
+ );
+
+NTSTATUS
+STDCALL
+ZwAdjustGroupsToken(
+ IN HANDLE TokenHandle,
+ IN BOOLEAN ResetToDefault,
+ IN PTOKEN_GROUPS NewState,
+ IN ULONG BufferLength,
+ OUT PTOKEN_GROUPS PreviousState,
+ OUT PULONG ReturnLength
+ );
+
+
+/*
+ * FUNCTION:
+ *
+ * ARGUMENTS:
+ * TokenHandle = Handle to the access token
+ * DisableAllPrivileges = The resulting suspend count.
+ NewState =
+ BufferLength =
+ PreviousState =
+ ReturnLength =
+ * REMARK:
+ * The arguments map to the win32 AdjustTokenPrivileges
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtAdjustPrivilegesToken(
+ IN HANDLE TokenHandle,
+ IN BOOLEAN DisableAllPrivileges,
+ IN PTOKEN_PRIVILEGES NewState,
+ IN ULONG BufferLength,
+ OUT PTOKEN_PRIVILEGES PreviousState,
+ OUT PULONG ReturnLength
+ );
+
+NTSTATUS
+STDCALL
+ZwAdjustPrivilegesToken(
+ IN HANDLE TokenHandle,
+ IN BOOLEAN DisableAllPrivileges,
+ IN PTOKEN_PRIVILEGES NewState,
+ IN ULONG BufferLength,
+ OUT PTOKEN_PRIVILEGES PreviousState,
+ OUT PULONG ReturnLength
+ );
+
+
+/*
+ * FUNCTION: Decrements a thread's suspend count and places it in an alerted
+ * state.
+ * ARGUMENTS:
+ * ThreadHandle = Handle to the thread that should be resumed
+ * SuspendCount = The resulting suspend count.
+ * REMARK:
+ * A thread is resumed if its suspend count is 0
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtAlertResumeThread(
+ IN HANDLE ThreadHandle,
+ OUT PULONG SuspendCount
+ );
+
+NTSTATUS
+STDCALL
+ZwAlertResumeThread(
+ IN HANDLE ThreadHandle,
+ OUT PULONG SuspendCount
+ );
+
+/*
+ * FUNCTION: Puts the thread in a alerted state
+ * ARGUMENTS:
+ * ThreadHandle = Handle to the thread that should be alerted
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtAlertThread(
+ IN HANDLE ThreadHandle
+ );
+
+NTSTATUS
+STDCALL
+ZwAlertThread(
+ IN HANDLE ThreadHandle
+ );
+
+
+/*
+ * FUNCTION: Allocates a locally unique id
+ * ARGUMENTS:
+ * LocallyUniqueId = Locally unique number
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtAllocateLocallyUniqueId(
+ OUT LUID *LocallyUniqueId
+ );
+
+NTSTATUS
+STDCALL
+ZwAllocateLocallyUniqueId(
+ OUT PLUID Luid
+ );
+
+/*
+ * FUNCTION: Allocates a block of virtual memory in the process address space
+ * ARGUMENTS:
+ * ProcessHandle = The handle of the process which owns the virtual memory
+ * BaseAddress = A pointer to the virtual memory allocated. If you supply a non zero
+ * value the system will try to allocate the memory at the address supplied. It rounds
+ * it down to a multiple if the page size.
+ * ZeroBits = (OPTIONAL) You can specify the number of high order bits that must be zero, ensuring that
+ * the memory will be allocated at a address below a certain value.
+ * RegionSize = The number of bytes to allocate
+ * AllocationType = Indicates the type of virtual memory you like to allocated,
+ * can be one of the values : MEM_COMMIT, MEM_RESERVE, MEM_RESET, MEM_TOP_DOWN
+ * Protect = Indicates the protection type of the pages allocated, can be a combination of
+ * PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE_READ,
+ * PAGE_EXECUTE_READWRITE, PAGE_GUARD, PAGE_NOACCESS, PAGE_NOACCESS
+ * REMARKS:
+ * This function maps to the win32 VirtualAllocEx. Virtual memory is process based so the
+ * protocol starts with a ProcessHandle. I splitted the functionality of obtaining the actual address and specifying
+ * the start address in two parameters ( BaseAddress and StartAddress ) The NumberOfBytesAllocated specify the range
+ * and the AllocationType and ProctectionType map to the other two parameters.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtAllocateVirtualMemory (
+ IN HANDLE ProcessHandle,
+ IN OUT PVOID *BaseAddress,
+ IN ULONG ZeroBits,
+ IN OUT PULONG RegionSize,
+ IN ULONG AllocationType,
+ IN ULONG Protect
+ );
+
+NTSTATUS
+STDCALL
+ZwAllocateVirtualMemory (
+ IN HANDLE ProcessHandle,
+ IN OUT PVOID *BaseAddress,
+ IN ULONG ZeroBits,
+ IN OUT PULONG RegionSize,
+ IN ULONG AllocationType,
+ IN ULONG Protect);
+
+/*
+ * FUNCTION: Returns from a callback into user mode
+ * ARGUMENTS:
+ * RETURN Status
+ */
+//FIXME: this function might need 3 parameters
+NTSTATUS STDCALL NtCallbackReturn(PVOID Result,
+ ULONG ResultLength,
+ NTSTATUS Status);
+
+NTSTATUS STDCALL ZwCallbackReturn(PVOID Result,
+ ULONG ResultLength,
+ NTSTATUS Status);
+
+/*
+ * FUNCTION: Cancels a IO request
+ * ARGUMENTS:
+ * FileHandle = Handle to the file
+ * IoStatusBlock =
+ *
+ * REMARKS:
+ * This function maps to the win32 CancelIo.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtCancelIoFile(
+ IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock
+ );
+
+NTSTATUS
+STDCALL
+ZwCancelIoFile(
+ IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock
+ );
+
+/*
+ * FUNCTION: Sets the status of the event back to non-signaled
+ * ARGUMENTS:
+ * EventHandle = Handle to the event
+ * REMARKS:
+ * This function maps to win32 function ResetEvent.
+ * RETURcNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtClearEvent(
+ IN HANDLE EventHandle
+ );
+
+NTSTATUS
+STDCALL
+ZwClearEvent(
+ IN HANDLE EventHandle
+ );
+
+/*
+ * FUNCTION: Closes an object handle
+ * ARGUMENTS:
+ * Handle = Handle to the object
+ * REMARKS:
+ * This function maps to the win32 function CloseHandle.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtClose(
+ IN HANDLE Handle
+ );
+
+NTSTATUS
+STDCALL
+ZwClose(
+ IN HANDLE Handle
+ );
+
+/*
+ * FUNCTION: Generates an audit message when a handle to an object is dereferenced
+ * ARGUMENTS:
+ * SubsystemName =
+ HandleId = Handle to the object
+ GenerateOnClose =
+ * REMARKS:
+ * This function maps to the win32 function ObjectCloseAuditAlarm.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtCloseObjectAuditAlarm(
+ IN PUNICODE_STRING SubsystemName,
+ IN PVOID HandleId,
+ IN BOOLEAN GenerateOnClose
+ );
+
+NTSTATUS
+STDCALL
+ZwCloseObjectAuditAlarm(
+ IN PUNICODE_STRING SubsystemName,
+ IN PVOID HandleId,
+ IN BOOLEAN GenerateOnClose
+ );
+
+/*
+ * FUNCTION: Creates a directory object
+ * ARGUMENTS:
+ * DirectoryHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Specifies access to the directory
+ * ObjectAttribute = Initialized attributes for the object
+ * REMARKS: This function maps to the win32 CreateDirectory. A directory is like a file so it needs a
+ * handle, a access mask and a OBJECT_ATTRIBUTES structure to map the path name and the SECURITY_ATTRIBUTES.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtCreateDirectoryObject(
+ OUT PHANDLE DirectoryHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+
+NTSTATUS
+STDCALL
+ZwCreateDirectoryObject(
+ OUT PHANDLE DirectoryHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+
+/*
+ * FUNCTION: Creates an event object
+ * ARGUMENTS:
+ * EventHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Specifies access to the event
+ * ObjectAttribute = Initialized attributes for the object
+ * ManualReset = manual-reset or auto-reset if true you have to reset the state of the event manually
+ * using NtResetEvent/NtClearEvent. if false the system will reset the event to a non-signalled state
+ * automatically after the system has rescheduled a thread waiting on the event.
+ * InitialState = specifies the initial state of the event to be signaled ( TRUE ) or non-signalled (FALSE).
+ * REMARKS: This function maps to the win32 CreateEvent. Demanding a out variable of type HANDLE,
+ * a access mask and a OBJECT_ATTRIBUTES structure mapping to the SECURITY_ATTRIBUTES. ManualReset and InitialState are
+ * both parameters aswell ( possibly the order is reversed ).
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtCreateEvent(
+ OUT PHANDLE EventHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN BOOLEAN ManualReset,
+ IN BOOLEAN InitialState
+ );
+
+NTSTATUS
+STDCALL
+ZwCreateEvent(
+ OUT PHANDLE EventHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN BOOLEAN ManualReset,
+ IN BOOLEAN InitialState
+ );
+
+/*
+ * FUNCTION: Creates an eventpair object
+ * ARGUMENTS:
+ * EventPairHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Specifies access to the event
+ * ObjectAttribute = Initialized attributes for the object
+ */
+
+NTSTATUS
+STDCALL
+NtCreateEventPair(
+ OUT PHANDLE EventPairHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+
+NTSTATUS
+STDCALL
+ZwCreateEventPair(
+ OUT PHANDLE EventPairHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+
+
+/*
+ * FUNCTION: Creates or opens a file, directory or device object.
+ * ARGUMENTS:
+ * FileHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Specifies the allowed or desired access to the file can
+ * be a combination of DELETE | FILE_READ_DATA ..
+ * ObjectAttribute = Initialized attributes for the object, contains the rootdirectory and the filename
+ * IoStatusBlock (OUT) = Caller supplied storage for the resulting status information, indicating if the
+ * the file is created and opened or allready existed and is just opened.
+ * FileAttributes = file attributes can be a combination of FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN ...
+ * ShareAccess = can be a combination of the following: FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE
+ * CreateDisposition = specifies what the behavior of the system if the file allready exists.
+ * CreateOptions = specifies the behavior of the system on file creation.
+ * EaBuffer (OPTIONAL) = Extended Attributes buffer, applies only to files and directories.
+ * EaLength = Extended Attributes buffer size, applies only to files and directories.
+ * REMARKS: This function maps to the win32 CreateFile.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtCreateFile(
+ OUT PHANDLE FileHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN PLARGE_INTEGER AllocationSize OPTIONAL,
+ IN ULONG FileAttributes,
+ IN ULONG ShareAccess,
+ IN ULONG CreateDisposition,
+ IN ULONG CreateOptions,
+ IN PVOID EaBuffer OPTIONAL,
+ IN ULONG EaLength
+ );
+
+NTSTATUS
+STDCALL
+ZwCreateFile(
+ OUT PHANDLE FileHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN PLARGE_INTEGER AllocationSize OPTIONAL,
+ IN ULONG FileAttributes,
+ IN ULONG ShareAccess,
+ IN ULONG CreateDisposition,
+ IN ULONG CreateOptions,
+ IN PVOID EaBuffer OPTIONAL,
+ IN ULONG EaLength
+ );
+
+/*
+ * FUNCTION: Creates or opens a file, directory or device object.
+ * ARGUMENTS:
+ * CompletionPort (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Specifies the allowed or desired access to the port
+ * IoStatusBlock =
+ * NumberOfConcurrentThreads =
+ * REMARKS: This function maps to the win32 CreateIoCompletionPort
+ * RETURNS:
+ * Status
+ */
+
+NTSTATUS
+STDCALL
+NtCreateIoCompletion(
+ OUT PHANDLE CompletionPort,
+ IN ACCESS_MASK DesiredAccess,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG NumberOfConcurrentThreads
+ );
+
+NTSTATUS
+STDCALL
+ZwCreateIoCompletion(
+ OUT PHANDLE CompletionPort,
+ IN ACCESS_MASK DesiredAccess,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG NumberOfConcurrentThreads
+ );
+
+
+/*
+ * FUNCTION: Creates a registry key
+ * ARGUMENTS:
+ * KeyHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Specifies the allowed or desired access to the key
+ * It can have a combination of the following values:
+ * KEY_READ | KEY_WRITE | KEY_EXECUTE | KEY_ALL_ACCESS
+ * or
+ * KEY_QUERY_VALUE The values of the key can be queried.
+ * KEY_SET_VALUE The values of the key can be modified.
+ * KEY_CREATE_SUB_KEYS The key may contain subkeys.
+ * KEY_ENUMERATE_SUB_KEYS Subkeys can be queried.
+ * KEY_NOTIFY
+ * KEY_CREATE_LINK A symbolic link to the key can be created.
+ * ObjectAttributes = The name of the key may be specified directly in the name field
+ * of object attributes or relative to a key in rootdirectory.
+ * TitleIndex = Might specify the position in the sequential order of subkeys.
+ * Class = Specifies the kind of data, for example REG_SZ for string data. [ ??? ]
+ * CreateOptions = Specifies additional options with which the key is created
+ * REG_OPTION_VOLATILE The key is not preserved across boots.
+ * REG_OPTION_NON_VOLATILE The key is preserved accross boots.
+ * REG_OPTION_CREATE_LINK The key is a symbolic link to another key.
+ * REG_OPTION_BACKUP_RESTORE Key is being opened or created for backup/restore operations.
+ * Disposition = Indicates if the call to NtCreateKey resulted in the creation of a key it
+ * can have the following values: REG_CREATED_NEW_KEY | REG_OPENED_EXISTING_KEY
+ * RETURNS:
+ * Status
+ */
+
+NTSTATUS STDCALL
+NtCreateKey(OUT PHANDLE KeyHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN ULONG TitleIndex,
+ IN PUNICODE_STRING Class OPTIONAL,
+ IN ULONG CreateOptions,
+ IN PULONG Disposition OPTIONAL);
+
+NTSTATUS STDCALL
+ZwCreateKey(OUT PHANDLE KeyHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN ULONG TitleIndex,
+ IN PUNICODE_STRING Class OPTIONAL,
+ IN ULONG CreateOptions,
+ IN PULONG Disposition OPTIONAL);
+
+/*
+ * FUNCTION: Creates a mail slot file
+ * ARGUMENTS:
+ * MailSlotFileHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Specifies the allowed or desired access to the file
+ * ObjectAttributes = Contains the name of the mailslotfile.
+ * IoStatusBlock =
+ * FileAttributes =
+ * ShareAccess =
+ * MaxMessageSize =
+ * TimeOut =
+ *
+ * REMARKS: This funciton maps to the win32 function CreateMailSlot
+ * RETURNS:
+ * Status
+ */
+
+NTSTATUS
+STDCALL
+NtCreateMailslotFile(
+ OUT PHANDLE MailSlotFileHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG FileAttributes,
+ IN ULONG ShareAccess,
+ IN ULONG MaxMessageSize,
+ IN PLARGE_INTEGER TimeOut
+ );
+
+NTSTATUS
+STDCALL
+ZwCreateMailslotFile(
+ OUT PHANDLE MailSlotFileHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG FileAttributes,
+ IN ULONG ShareAccess,
+ IN ULONG MaxMessageSize,
+ IN PLARGE_INTEGER TimeOut
+ );
+
+/*
+ * FUNCTION: Creates or opens a mutex
+ * ARGUMENTS:
+ * MutantHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Specifies the allowed or desired access to the port
+ * ObjectAttributes = Contains the name of the mutex.
+ * InitialOwner = If true the calling thread acquires ownership
+ * of the mutex.
+ * REMARKS: This funciton maps to the win32 function CreateMutex
+ * RETURNS:
+ * Status
+ */
+NTSTATUS
+STDCALL
+NtCreateMutant(
+ OUT PHANDLE MutantHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN BOOLEAN InitialOwner
+ );
+
+NTSTATUS
+STDCALL
+ZwCreateMutant(
+ OUT PHANDLE MutantHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN BOOLEAN InitialOwner
+ );
+
+/*
+ * FUNCTION: Creates a process.
+ * ARGUMENTS:
+ * ProcessHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Specifies the allowed or desired access to the process can
+ * be a combinate of STANDARD_RIGHTS_REQUIRED| ..
+ * ObjectAttribute = Initialized attributes for the object, contains the rootdirectory and the filename
+ * ParentProcess = Handle to the parent process.
+ * InheritObjectTable = Specifies to inherit the objects of the parent process if true.
+ * SectionHandle = Handle to a section object to back the image file
+ * DebugPort = Handle to a DebugPort if NULL the system default debug port will be used.
+ * ExceptionPort = Handle to a exception port.
+ * REMARKS:
+ * This function maps to the win32 CreateProcess.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtCreateProcess(
+ OUT PHANDLE ProcessHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN HANDLE ParentProcess,
+ IN BOOLEAN InheritObjectTable,
+ IN HANDLE SectionHandle OPTIONAL,
+ IN HANDLE DebugPort OPTIONAL,
+ IN HANDLE ExceptionPort OPTIONAL
+ );
+
+NTSTATUS
+STDCALL
+ZwCreateProcess(
+ OUT PHANDLE ProcessHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN HANDLE ParentProcess,
+ IN BOOLEAN InheritObjectTable,
+ IN HANDLE SectionHandle OPTIONAL,
+ IN HANDLE DebugPort OPTIONAL,
+ IN HANDLE ExceptionPort OPTIONAL
+ );
+
+/*
+ * FUNCTION: Creates a section object.
+ * ARGUMENTS:
+ * SectionHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Specifies the desired access to the section can be a combination of STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_WRITE |
+ * SECTION_MAP_READ | SECTION_MAP_EXECUTE.
+ * ObjectAttribute = Initialized attributes for the object can be used to create a named section
+ * MaxiumSize = Maximizes the size of the memory section. Must be non-NULL for a page-file backed section.
+ * If value specified for a mapped file and the file is not large enough, file will be extended.
+ * SectionPageProtection = Can be a combination of PAGE_READONLY | PAGE_READWRITE | PAGE_WRITEONLY | PAGE_WRITECOPY.
+ * AllocationAttributes = can be a combination of SEC_IMAGE | SEC_RESERVE
+ * FileHanlde = Handle to a file to create a section mapped to a file instead of a memory backed section.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtCreateSection(
+ OUT PHANDLE SectionHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN PLARGE_INTEGER MaximumSize OPTIONAL,
+ IN ULONG SectionPageProtection OPTIONAL,
+ IN ULONG AllocationAttributes,
+ IN HANDLE FileHandle OPTIONAL
+ );
+
+NTSTATUS
+STDCALL
+ZwCreateSection(
+ OUT PHANDLE SectionHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN PLARGE_INTEGER MaximumSize OPTIONAL,
+ IN ULONG SectionPageProtection OPTIONAL,
+ IN ULONG AllocationAttributes,
+ IN HANDLE FileHandle OPTIONAL
+ );
+
+/*
+ * FUNCTION: Creates a semaphore object for interprocess synchronization.
+ * ARGUMENTS:
+ * SemaphoreHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Specifies the allowed or desired access to the semaphore.
+ * ObjectAttribute = Initialized attributes for the object.
+ * InitialCount = Not necessary zero, might be smaller than zero.
+ * MaximumCount = Maxiumum count the semaphore can reach.
+ * RETURNS: Status
+ * REMARKS:
+ * The semaphore is set to signaled when its count is greater than zero, and non-signaled when its count is zero.
+ */
+
+//FIXME: should a semaphore's initial count allowed to be smaller than zero ??
+NTSTATUS
+STDCALL
+NtCreateSemaphore(
+ OUT PHANDLE SemaphoreHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN LONG InitialCount,
+ IN LONG MaximumCount
+ );
+
+NTSTATUS
+STDCALL
+ZwCreateSemaphore(
+ OUT PHANDLE SemaphoreHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN LONG InitialCount,
+ IN LONG MaximumCount
+ );
+
+/*
+ * FUNCTION: Creates a symbolic link object
+ * ARGUMENTS:
+ * SymbolicLinkHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Specifies the allowed or desired access to the thread.
+ * ObjectAttributes = Initialized attributes for the object.
+ * Name = Target name of the symbolic link
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtCreateSymbolicLinkObject(
+ OUT PHANDLE SymbolicLinkHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN PUNICODE_STRING Name
+ );
+
+NTSTATUS
+STDCALL
+ZwCreateSymbolicLinkObject(
+ OUT PHANDLE SymbolicLinkHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN PUNICODE_STRING Name
+ );
+
+/*
+ * FUNCTION: Creates a waitable timer.
+ * ARGUMENTS:
+ * TimerHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Specifies the allowed or desired access to the timer.
+ * ObjectAttributes = Initialized attributes for the object.
+ * TimerType = Specifies if the timer should be reset manually.
+ * REMARKS:
+ * This function maps to the win32 CreateWaitableTimer. lpTimerAttributes and lpTimerName map to
+ * corresponding fields in OBJECT_ATTRIBUTES structure.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtCreateTimer(
+ OUT PHANDLE TimerHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN TIMER_TYPE TimerType
+ );
+
+NTSTATUS
+STDCALL
+ZwCreateTimer(
+ OUT PHANDLE TimerHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN TIMER_TYPE TimerType
+ );
+
+/*
+ * FUNCTION: Creates a token.
+ * ARGUMENTS:
+ * TokenHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Specifies the allowed or desired access to the process can
+ * be a combinate of STANDARD_RIGHTS_REQUIRED| ..
+ * ObjectAttribute = Initialized attributes for the object, contains the rootdirectory and the filename
+ * TokenType =
+ * AuthenticationId =
+ * ExpirationTime =
+ * TokenUser =
+ * TokenGroups =
+ * TokenPrivileges =
+ * TokenOwner =
+ * TokenPrimaryGroup =
+ * TokenDefaultDacl =
+ * TokenSource =
+ * REMARKS:
+ * This function does not map to a win32 function
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtCreateToken(
+ OUT PHANDLE TokenHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN TOKEN_TYPE TokenType,
+ IN PLUID AuthenticationId,
+ IN PLARGE_INTEGER ExpirationTime,
+ IN PTOKEN_USER TokenUser,
+ IN PTOKEN_GROUPS TokenGroups,
+ IN PTOKEN_PRIVILEGES TokenPrivileges,
+ IN PTOKEN_OWNER TokenOwner,
+ IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup,
+ IN PTOKEN_DEFAULT_DACL TokenDefaultDacl,
+ IN PTOKEN_SOURCE TokenSource
+ );
+
+NTSTATUS
+STDCALL
+ZwCreateToken(
+ OUT PHANDLE TokenHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN TOKEN_TYPE TokenType,
+ IN PLUID AuthenticationId,
+ IN PLARGE_INTEGER ExpirationTime,
+ IN PTOKEN_USER TokenUser,
+ IN PTOKEN_GROUPS TokenGroups,
+ IN PTOKEN_PRIVILEGES TokenPrivileges,
+ IN PTOKEN_OWNER TokenOwner,
+ IN PTOKEN_PRIMARY_GROUP TokenPrimaryGroup,
+ IN PTOKEN_DEFAULT_DACL TokenDefaultDacl,
+ IN PTOKEN_SOURCE TokenSource
+ );
+
+/*
+ * FUNCTION: Returns the callers thread TEB.
+ * RETURNS: The resulting teb.
+ */
+#if 0
+ NT_TEB *
+STDCALL
+NtCurrentTeb(VOID
+ );
+#endif
+
+/*
+ * FUNCTION: Deletes an atom from the global atom table
+ * ARGUMENTS:
+ * Atom = Identifies the atom to delete
+ * REMARKS:
+ * The function maps to the win32 GlobalDeleteAtom
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtDeleteAtom(
+ IN RTL_ATOM Atom
+ );
+
+NTSTATUS
+STDCALL
+ZwDeleteAtom(
+ IN RTL_ATOM Atom
+ );
+
+/*
+ * FUNCTION: Deletes a file or a directory
+ * ARGUMENTS:
+ * ObjectAttributes = Name of the file which should be deleted
+ * REMARKS:
+ * This system call is functionally equivalent to NtSetInformationFile
+ * setting the disposition information.
+ * The function maps to the win32 DeleteFile.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtDeleteFile(
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+
+NTSTATUS
+STDCALL
+ZwDeleteFile(
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+
+/*
+ * FUNCTION: Deletes a registry key
+ * ARGUMENTS:
+ * KeyHandle = Handle of the key
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtDeleteKey(
+ IN HANDLE KeyHandle
+ );
+NTSTATUS
+STDCALL
+ZwDeleteKey(
+ IN HANDLE KeyHandle
+ );
+
+/*
+ * FUNCTION: Generates a audit message when an object is deleted
+ * ARGUMENTS:
+ * SubsystemName = Spefies the name of the subsystem can be 'WIN32' or 'DEBUG'
+ * HandleId= Handle to an audit object
+ * GenerateOnClose = Value returned by NtAccessCheckAndAuditAlarm
+ * REMARKS: This function maps to the win32 ObjectCloseAuditAlarm
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtDeleteObjectAuditAlarm (
+ IN PUNICODE_STRING SubsystemName,
+ IN PVOID HandleId,
+ IN BOOLEAN GenerateOnClose
+ );
+
+NTSTATUS
+STDCALL
+ZwDeleteObjectAuditAlarm (
+ IN PUNICODE_STRING SubsystemName,
+ IN PVOID HandleId,
+ IN BOOLEAN GenerateOnClose
+ );
+
+
+/*
+ * FUNCTION: Deletes a value from a registry key
+ * ARGUMENTS:
+ * KeyHandle = Handle of the key
+ * ValueName = Name of the value to delete
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtDeleteValueKey(
+ IN HANDLE KeyHandle,
+ IN PUNICODE_STRING ValueName
+ );
+
+NTSTATUS
+STDCALL
+ZwDeleteValueKey(
+ IN HANDLE KeyHandle,
+ IN PUNICODE_STRING ValueName
+ );
+/*
+ * FUNCTION: Sends IOCTL to the io sub system
+ * ARGUMENTS:
+ * DeviceHandle = Points to the handle that is created by NtCreateFile
+ * Event = Event to synchronize on STATUS_PENDING
+ * ApcRoutine = Asynchroneous procedure callback
+ * ApcContext = Callback context.
+ * IoStatusBlock = Caller should supply storage for extra information..
+ * IoControlCode = Contains the IO Control command. This is an
+ * index to the structures in InputBuffer and OutputBuffer.
+ * InputBuffer = Caller should supply storage for input buffer if IOTL expects one.
+ * InputBufferSize = Size of the input bufffer
+ * OutputBuffer = Caller should supply storage for output buffer if IOTL expects one.
+ * OutputBufferSize = Size of the input bufffer
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtDeviceIoControlFile(
+ IN HANDLE DeviceHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
+ IN PVOID UserApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG IoControlCode,
+ IN PVOID InputBuffer,
+ IN ULONG InputBufferSize,
+ OUT PVOID OutputBuffer,
+ IN ULONG OutputBufferSize
+ );
+
+NTSTATUS
+STDCALL
+ZwDeviceIoControlFile(
+ IN HANDLE DeviceHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
+ IN PVOID UserApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG IoControlCode,
+ IN PVOID InputBuffer,
+ IN ULONG InputBufferSize,
+ OUT PVOID OutputBuffer,
+ IN ULONG OutputBufferSize
+ );
+/*
+ * FUNCTION: Displays a string on the blue screen
+ * ARGUMENTS:
+ * DisplayString = The string to display
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtDisplayString(
+ IN PUNICODE_STRING DisplayString
+ );
+
+NTSTATUS
+STDCALL
+ZwDisplayString(
+ IN PUNICODE_STRING DisplayString
+ );
+
+/*
+ * FUNCTION: Returns information about the subkeys of an open key
+ * ARGUMENTS:
+ * KeyHandle = Handle of the key whose subkeys are to enumerated
+ * Index = zero based index of the subkey for which information is
+ * request
+ * KeyInformationClass = Type of information returned
+ * KeyInformation (OUT) = Caller allocated buffer for the information
+ * about the key
+ * Length = Length in bytes of the KeyInformation buffer
+ * ResultLength (OUT) = Caller allocated storage which holds
+ * the number of bytes of information retrieved
+ * on return
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtEnumerateKey(
+ IN HANDLE KeyHandle,
+ IN ULONG Index,
+ IN KEY_INFORMATION_CLASS KeyInformationClass,
+ OUT PVOID KeyInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+
+NTSTATUS
+STDCALL
+ZwEnumerateKey(
+ IN HANDLE KeyHandle,
+ IN ULONG Index,
+ IN KEY_INFORMATION_CLASS KeyInformationClass,
+ OUT PVOID KeyInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+/*
+ * FUNCTION: Returns information about the value entries of an open key
+ * ARGUMENTS:
+ * KeyHandle = Handle of the key whose value entries are to enumerated
+ * Index = zero based index of the subkey for which information is
+ * request
+ * KeyInformationClass = Type of information returned
+ * KeyInformation (OUT) = Caller allocated buffer for the information
+ * about the key
+ * Length = Length in bytes of the KeyInformation buffer
+ * ResultLength (OUT) = Caller allocated storage which holds
+ * the number of bytes of information retrieved
+ * on return
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtEnumerateValueKey(
+ IN HANDLE KeyHandle,
+ IN ULONG Index,
+ IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
+ OUT PVOID KeyValueInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+
+NTSTATUS
+STDCALL
+ZwEnumerateValueKey(
+ IN HANDLE KeyHandle,
+ IN ULONG Index,
+ IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
+ OUT PVOID KeyValueInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+
+/*
+ * FUNCTION: Flushes chached file data to disk
+ * ARGUMENTS:
+ * FileHandle = Points to the file
+ * IoStatusBlock = Caller must supply storage to receive the result of the flush
+ * buffers operation. The information field is set to number of bytes
+ * flushed to disk.
+ * RETURNS: Status
+ * REMARKS:
+ * This funciton maps to the win32 FlushFileBuffers
+ */
+NTSTATUS
+STDCALL
+NtFlushBuffersFile(
+ IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock
+ );
+
+NTSTATUS
+STDCALL
+ZwFlushBuffersFile(
+ IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock
+ );
+
+/*
+ * FUNCTION: Flushes a registry key to disk
+ * ARGUMENTS:
+ * KeyHandle = Points to the registry key handle
+ * RETURNS: Status
+ * REMARKS:
+ * This funciton maps to the win32 RegFlushKey.
+ */
+NTSTATUS
+STDCALL
+NtFlushKey(
+ IN HANDLE KeyHandle
+ );
+
+NTSTATUS
+STDCALL
+ZwFlushKey(
+ IN HANDLE KeyHandle
+ );
+
+/*
+ * FUNCTION: Flushes the dirty pages to file
+ * RETURNS: Status
+ * FIXME: Not sure this does (how is the file specified)
+ */
+NTSTATUS STDCALL NtFlushWriteBuffer(VOID);
+NTSTATUS STDCALL ZwFlushWriteBuffer(VOID);
+
+ /*
+ * FUNCTION: Frees a range of virtual memory
+ * ARGUMENTS:
+ * ProcessHandle = Points to the process that allocated the virtual
+ * memory
+ * BaseAddress = Points to the memory address, rounded down to a
+ * multiple of the pagesize
+ * RegionSize = Limits the range to free, rounded up to a multiple of
+ * the paging size
+ * FreeType = Can be one of the values: MEM_DECOMMIT, or MEM_RELEASE
+ * RETURNS: Status
+ */
+NTSTATUS STDCALL NtFreeVirtualMemory(IN HANDLE ProcessHandle,
+ IN PVOID *BaseAddress,
+ IN PULONG RegionSize,
+ IN ULONG FreeType);
+NTSTATUS STDCALL ZwFreeVirtualMemory(IN HANDLE ProcessHandle,
+ IN PVOID *BaseAddress,
+ IN PULONG RegionSize,
+ IN ULONG FreeType);
+
+/*
+ * FUNCTION: Sends FSCTL to the filesystem
+ * ARGUMENTS:
+ * DeviceHandle = Points to the handle that is created by NtCreateFile
+ * Event = Event to synchronize on STATUS_PENDING
+ * ApcRoutine =
+ * ApcContext =
+ * IoStatusBlock = Caller should supply storage for
+ * IoControlCode = Contains the File System Control command. This is an
+ * index to the structures in InputBuffer and OutputBuffer.
+ * FSCTL_GET_RETRIEVAL_POINTERS MAPPING_PAIR
+ * FSCTL_GET_RETRIEVAL_POINTERS GET_RETRIEVAL_DESCRIPTOR
+ * FSCTL_GET_VOLUME_BITMAP BITMAP_DESCRIPTOR
+ * FSCTL_MOVE_FILE MOVEFILE_DESCRIPTOR
+ *
+ * InputBuffer = Caller should supply storage for input buffer if FCTL expects one.
+ * InputBufferSize = Size of the input bufffer
+ * OutputBuffer = Caller should supply storage for output buffer if FCTL expects one.
+ * OutputBufferSize = Size of the input bufffer
+ * RETURNS: Status [ STATUS_SUCCESS | STATUS_PENDING | STATUS_ACCESS_DENIED | STATUS_INSUFFICIENT_RESOURCES |
+ * STATUS_INVALID_PARAMETER | STATUS_INVALID_DEVICE_REQUEST ]
+ */
+NTSTATUS
+STDCALL
+NtFsControlFile(
+ IN HANDLE DeviceHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG IoControlCode,
+ IN PVOID InputBuffer,
+ IN ULONG InputBufferSize,
+ OUT PVOID OutputBuffer,
+ IN ULONG OutputBufferSize
+ );
+
+NTSTATUS
+STDCALL
+ZwFsControlFile(
+ IN HANDLE DeviceHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG IoControlCode,
+ IN PVOID InputBuffer,
+ IN ULONG InputBufferSize,
+ OUT PVOID OutputBuffer,
+ IN ULONG OutputBufferSize
+ );
+
+/*
+ * FUNCTION: Retrieves the processor context of a thread
+ * ARGUMENTS:
+ * ThreadHandle = Handle to a thread
+ * Context (OUT) = Caller allocated storage for the processor context
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtGetContextThread(
+ IN HANDLE ThreadHandle,
+ OUT PCONTEXT Context
+ );
+
+NTSTATUS
+STDCALL
+ZwGetContextThread(
+ IN HANDLE ThreadHandle,
+ OUT PCONTEXT Context
+ );
+
+/*
+ * FUNCTION: Sets a thread to impersonate another
+ * ARGUMENTS:
+ * ThreadHandle = Server thread that will impersonate a client.
+ ThreadToImpersonate = Client thread that will be impersonated
+ SecurityQualityOfService = Specifies the impersonation level.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtImpersonateThread(
+ IN HANDLE ThreadHandle,
+ IN HANDLE ThreadToImpersonate,
+ IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService
+ );
+
+NTSTATUS
+STDCALL
+ZwImpersonateThread(
+ IN HANDLE ThreadHandle,
+ IN HANDLE ThreadToImpersonate,
+ IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService
+ );
+
+/*
+ * FUNCTION: Initializes the registry.
+ * ARGUMENTS:
+ * SetUpBoot = This parameter is true for a setup boot.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtInitializeRegistry(
+ BOOLEAN SetUpBoot
+ );
+NTSTATUS
+STDCALL
+ZwInitializeRegistry(
+ BOOLEAN SetUpBoot
+ );
+
+/*
+ * FUNCTION: Loads a driver.
+ * ARGUMENTS:
+ * DriverServiceName = Name of the driver to load
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtLoadDriver(
+ IN PUNICODE_STRING DriverServiceName
+ );
+
+NTSTATUS
+STDCALL
+ZwLoadDriver(
+ IN PUNICODE_STRING DriverServiceName
+ );
+
+/*
+ * FUNCTION: Locks a range of bytes in a file.
+ * ARGUMENTS:
+ * FileHandle = Handle to the file
+ * Event = Should be null if apc is specified.
+ * ApcRoutine = Asynchroneous Procedure Callback
+ * ApcContext = Argument to the callback
+ * IoStatusBlock (OUT) = Caller should supply storage for a structure containing
+ * the completion status and information about the requested lock operation.
+ * ByteOffset = Offset
+ * Length = Number of bytes to lock.
+ * Key = Special value to give other threads the possibility to unlock the file
+ by supplying the key in a call to NtUnlockFile.
+ * FailImmediatedly = If false the request will block untill the lock is obtained.
+ * ExclusiveLock = Specifies whether a exclusive or a shared lock is obtained.
+ * REMARK:
+ This procedure maps to the win32 procedure LockFileEx. STATUS_PENDING is returned if the lock could
+ not be obtained immediately, the device queue is busy and the IRP is queued.
+ * RETURNS: Status [ STATUS_SUCCESS | STATUS_PENDING | STATUS_ACCESS_DENIED | STATUS_INSUFFICIENT_RESOURCES |
+ STATUS_INVALID_PARAMETER | STATUS_INVALID_DEVICE_REQUEST | STATUS_LOCK_NOT_GRANTED ]
+
+ */
+NTSTATUS
+STDCALL
+NtLockFile(
+ IN HANDLE FileHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN PLARGE_INTEGER ByteOffset,
+ IN PLARGE_INTEGER Length,
+ IN PULONG Key,
+ IN BOOLEAN FailImmediatedly,
+ IN BOOLEAN ExclusiveLock
+ );
+
+NTSTATUS
+STDCALL
+ZwLockFile(
+ IN HANDLE FileHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN PLARGE_INTEGER ByteOffset,
+ IN PLARGE_INTEGER Length,
+ IN PULONG Key,
+ IN BOOLEAN FailImmediatedly,
+ IN BOOLEAN ExclusiveLock
+ );
+
+/*
+ * FUNCTION: Makes temporary object that will be removed at next boot.
+ * ARGUMENTS:
+ * Handle = Handle to object
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtMakeTemporaryObject(
+ IN HANDLE Handle
+ );
+
+NTSTATUS
+STDCALL
+ZwMakeTemporaryObject(
+ IN HANDLE Handle
+ );
+/*
+ * FUNCTION: Maps a view of a section into the virtual address space of a
+ * process
+ * ARGUMENTS:
+ * SectionHandle = Handle of the section
+ * ProcessHandle = Handle of the process
+ * BaseAddress = Desired base address (or NULL) on entry
+ * Actual base address of the view on exit
+ * ZeroBits = Number of high order address bits that must be zero
+ * CommitSize = Size in bytes of the initially committed section of
+ * the view
+ * SectionOffset = Offset in bytes from the beginning of the section
+ * to the beginning of the view
+ * ViewSize = Desired length of map (or zero to map all) on entry
+ * Actual length mapped on exit
+ * InheritDisposition = Specified how the view is to be shared with
+ * child processes
+ * AllocateType = Type of allocation for the pages
+ * Protect = Protection for the committed region of the view
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtMapViewOfSection(
+ IN HANDLE SectionHandle,
+ IN HANDLE ProcessHandle,
+ IN OUT PVOID *BaseAddress,
+ IN ULONG ZeroBits,
+ IN ULONG CommitSize,
+ IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
+ IN OUT PULONG ViewSize,
+ IN SECTION_INHERIT InheritDisposition,
+ IN ULONG AllocationType,
+ IN ULONG AccessProtection
+ );
+
+NTSTATUS
+STDCALL
+ZwMapViewOfSection(
+ IN HANDLE SectionHandle,
+ IN HANDLE ProcessHandle,
+ IN OUT PVOID *BaseAddress,
+ IN ULONG ZeroBits,
+ IN ULONG CommitSize,
+ IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,
+ IN OUT PULONG ViewSize,
+ IN SECTION_INHERIT InheritDisposition,
+ IN ULONG AllocationType,
+ IN ULONG AccessProtection
+ );
+
+/*
+ * FUNCTION: Installs a notify for the change of a directory's contents
+ * ARGUMENTS:
+ * FileHandle = Handle to the directory
+ Event =
+ * ApcRoutine = Start address
+ * ApcContext = Delimits the range of virtual memory
+ * for which the new access protection holds
+ * IoStatusBlock = The new access proctection for the pages
+ * Buffer = Caller supplies storage for resulting information --> FILE_NOTIFY_INFORMATION
+ * BufferSize = Size of the buffer
+ CompletionFilter = Can be one of the following values:
+ FILE_NOTIFY_CHANGE_FILE_NAME
+ FILE_NOTIFY_CHANGE_DIR_NAME
+ FILE_NOTIFY_CHANGE_NAME ( FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME )
+ FILE_NOTIFY_CHANGE_ATTRIBUTES
+ FILE_NOTIFY_CHANGE_SIZE
+ FILE_NOTIFY_CHANGE_LAST_WRITE
+ FILE_NOTIFY_CHANGE_LAST_ACCESS
+ FILE_NOTIFY_CHANGE_CREATION ( change of creation timestamp )
+ FILE_NOTIFY_CHANGE_EA
+ FILE_NOTIFY_CHANGE_SECURITY
+ FILE_NOTIFY_CHANGE_STREAM_NAME
+ FILE_NOTIFY_CHANGE_STREAM_SIZE
+ FILE_NOTIFY_CHANGE_STREAM_WRITE
+ WatchTree = If true the notify will be installed recursively on the targetdirectory and all subdirectories.
+ *
+ * REMARKS:
+ * The function maps to the win32 FindFirstChangeNotification, FindNextChangeNotification
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtNotifyChangeDirectoryFile(
+ IN HANDLE FileHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID Buffer,
+ IN ULONG BufferSize,
+ IN ULONG CompletionFilter,
+ IN BOOLEAN WatchTree
+ );
+
+NTSTATUS
+STDCALL
+ZwNotifyChangeDirectoryFile(
+ IN HANDLE FileHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID Buffer,
+ IN ULONG BufferSize,
+ IN ULONG CompletionFilter,
+ IN BOOLEAN WatchTree
+ );
+
+/*
+ * FUNCTION: Installs a notfication callback on registry changes
+ * ARGUMENTS:
+ KeyHandle = Handle to the registry key
+ Event = Event that should be signalled on modification of the key
+ ApcRoutine = Routine that should be called on modification of the key
+ ApcContext = Argument to the ApcRoutine
+ IoStatusBlock = ???
+ CompletionFilter = Specifies the kind of notification the caller likes to receive.
+ Can be a combination of the following values:
+
+ REG_NOTIFY_CHANGE_NAME
+ REG_NOTIFY_CHANGE_ATTRIBUTES
+ REG_NOTIFY_CHANGE_LAST_SET
+ REG_NOTIFY_CHANGE_SECURITY
+
+
+ Asynchroneous = If TRUE the changes are reported by signalling an event if false
+ the function will not return before a change occurs.
+ ChangeBuffer = Will return the old value
+ Length = Size of the change buffer
+ WatchSubtree = Indicates if the caller likes to receive a notification of changes in
+ sub keys or not.
+ * REMARKS: If the key is closed the event is signalled aswell.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtNotifyChangeKey(
+ IN HANDLE KeyHandle,
+ IN HANDLE Event,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG CompletionFilter,
+ IN BOOLEAN Asynchroneous,
+ OUT PVOID ChangeBuffer,
+ IN ULONG Length,
+ IN BOOLEAN WatchSubtree
+ );
+
+NTSTATUS
+STDCALL
+ZwNotifyChangeKey(
+ IN HANDLE KeyHandle,
+ IN HANDLE Event,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG CompletionFilter,
+ IN BOOLEAN Asynchroneous,
+ OUT PVOID ChangeBuffer,
+ IN ULONG Length,
+ IN BOOLEAN WatchSubtree
+ );
+
+/*
+ * FUNCTION: Opens an existing directory object
+ * ARGUMENTS:
+ * FileHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Requested access to the directory
+ * ObjectAttributes = Initialized attributes for the object
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtOpenDirectoryObject(
+ OUT PHANDLE FileHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+NTSTATUS
+STDCALL
+ZwOpenDirectoryObject(
+ OUT PHANDLE FileHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+
+/*
+ * FUNCTION: Opens an existing event
+ * ARGUMENTS:
+ * EventHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Requested access to the event
+ * ObjectAttributes = Initialized attributes for the object
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtOpenEvent(
+ OUT PHANDLE EventHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+
+NTSTATUS
+STDCALL
+ZwOpenEvent(
+ OUT PHANDLE EventHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+
+/*
+ * FUNCTION: Opens an existing event pair
+ * ARGUMENTS:
+ * EventHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Requested access to the event
+ * ObjectAttributes = Initialized attributes for the object
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtOpenEventPair(
+ OUT PHANDLE EventPairHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+
+NTSTATUS
+STDCALL
+ZwOpenEventPair(
+ OUT PHANDLE EventPairHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+/*
+ * FUNCTION: Opens an existing file
+ * ARGUMENTS:
+ * FileHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Requested access to the file
+ * ObjectAttributes = Initialized attributes for the object
+ * IoStatusBlock =
+ * ShareAccess =
+ * OpenOptions =
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtOpenFile(
+ OUT PHANDLE FileHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG ShareAccess,
+ IN ULONG OpenOptions
+ );
+
+NTSTATUS
+STDCALL
+ZwOpenFile(
+ OUT PHANDLE FileHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG ShareAccess,
+ IN ULONG OpenOptions
+ );
+
+/*
+ * FUNCTION: Opens an existing io completion object
+ * ARGUMENTS:
+ * CompletionPort (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Requested access to the io completion object
+ * ObjectAttributes = Initialized attributes for the object
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtOpenIoCompletion(
+ OUT PHANDLE CompetionPort,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+
+NTSTATUS
+STDCALL
+ZwOpenIoCompletion(
+ OUT PHANDLE CompetionPort,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+
+/*
+ * FUNCTION: Opens an existing key in the registry
+ * ARGUMENTS:
+ * KeyHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Requested access to the key
+ * ObjectAttributes = Initialized attributes for the object
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtOpenKey(
+ OUT PHANDLE KeyHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+
+NTSTATUS
+STDCALL
+ZwOpenKey(
+ OUT PHANDLE KeyHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+/*
+ * FUNCTION: Opens an existing key in the registry
+ * ARGUMENTS:
+ * MutantHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Requested access to the mutant
+ * ObjectAttribute = Initialized attributes for the object
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtOpenMutant(
+ OUT PHANDLE MutantHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+NTSTATUS
+STDCALL
+ZwOpenMutant(
+ OUT PHANDLE MutantHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+
+/*
+ * FUNCTION: Opens an existing process
+ * ARGUMENTS:
+ * ProcessHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Requested access to the process
+ * ObjectAttribute = Initialized attributes for the object
+ * ClientId = Identifies the process id to open
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtOpenProcess (
+ OUT PHANDLE ProcessHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN PCLIENT_ID ClientId
+ );
+NTSTATUS
+STDCALL
+ZwOpenProcess (
+ OUT PHANDLE ProcessHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN PCLIENT_ID ClientId
+ );
+/*
+ * FUNCTION: Opens an existing process
+ * ARGUMENTS:
+ * ProcessHandle = Handle of the process of which owns the token
+ * DesiredAccess = Requested access to the token
+ * TokenHandle (OUT) = Caller supplies storage for the resulting token.
+ * REMARKS:
+ This function maps to the win32
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtOpenProcessToken(
+ IN HANDLE ProcessHandle,
+ IN ACCESS_MASK DesiredAccess,
+ OUT PHANDLE TokenHandle
+ );
+
+NTSTATUS
+STDCALL
+ZwOpenProcessToken(
+ IN HANDLE ProcessHandle,
+ IN ACCESS_MASK DesiredAccess,
+ OUT PHANDLE TokenHandle
+ );
+
+/*
+ * FUNCTION: Opens an existing section object
+ * ARGUMENTS:
+ * KeyHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Requested access to the key
+ * ObjectAttribute = Initialized attributes for the object
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtOpenSection(
+ OUT PHANDLE SectionHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+NTSTATUS
+STDCALL
+ZwOpenSection(
+ OUT PHANDLE SectionHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+/*
+ * FUNCTION: Opens an existing semaphore
+ * ARGUMENTS:
+ * SemaphoreHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Requested access to the semaphore
+ * ObjectAttribute = Initialized attributes for the object
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtOpenSemaphore(
+ IN HANDLE SemaphoreHandle,
+ IN ACCESS_MASK DesiredAcces,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+NTSTATUS
+STDCALL
+ZwOpenSemaphore(
+ IN HANDLE SemaphoreHandle,
+ IN ACCESS_MASK DesiredAcces,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+/*
+ * FUNCTION: Opens an existing symbolic link
+ * ARGUMENTS:
+ * SymbolicLinkHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Requested access to the symbolic link
+ * ObjectAttribute = Initialized attributes for the object
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtOpenSymbolicLinkObject(
+ OUT PHANDLE SymbolicLinkHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+NTSTATUS
+STDCALL
+ZwOpenSymbolicLinkObject(
+ OUT PHANDLE SymbolicLinkHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+/*
+ * FUNCTION: Opens an existing thread
+ * ARGUMENTS:
+ * ThreadHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Requested access to the thread
+ * ObjectAttribute = Initialized attributes for the object
+ * ClientId = Identifies the thread to open.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtOpenThread(
+ OUT PHANDLE ThreadHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN PCLIENT_ID ClientId
+ );
+NTSTATUS
+STDCALL
+ZwOpenThread(
+ OUT PHANDLE ThreadHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN PCLIENT_ID ClientId
+ );
+
+NTSTATUS
+STDCALL
+NtOpenThreadToken(
+ IN HANDLE ThreadHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN BOOLEAN OpenAsSelf,
+ OUT PHANDLE TokenHandle
+ );
+
+NTSTATUS
+STDCALL
+ZwOpenThreadToken(
+ IN HANDLE ThreadHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN BOOLEAN OpenAsSelf,
+ OUT PHANDLE TokenHandle
+ );
+/*
+ * FUNCTION: Opens an existing timer
+ * ARGUMENTS:
+ * TimerHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Requested access to the timer
+ * ObjectAttribute = Initialized attributes for the object
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtOpenTimer(
+ OUT PHANDLE TimerHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+NTSTATUS
+STDCALL
+ZwOpenTimer(
+ OUT PHANDLE TimerHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes
+ );
+
+/*
+ * FUNCTION: Checks an access token for specific privileges
+ * ARGUMENTS:
+ * ClientToken = Handle to a access token structure
+ * RequiredPrivileges = Specifies the requested privileges.
+ * Result = Caller supplies storage for the result. If PRIVILEGE_SET_ALL_NECESSARY is
+ set in the Control member of PRIVILEGES_SET Result
+ will only be TRUE if all privileges are present in the access token.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtPrivilegeCheck(
+ IN HANDLE ClientToken,
+ IN PPRIVILEGE_SET RequiredPrivileges,
+ IN PBOOLEAN Result
+ );
+
+NTSTATUS
+STDCALL
+ZwPrivilegeCheck(
+ IN HANDLE ClientToken,
+ IN PPRIVILEGE_SET RequiredPrivileges,
+ IN PBOOLEAN Result
+ );
+
+NTSTATUS
+STDCALL
+NtPrivilegedServiceAuditAlarm(
+ IN PUNICODE_STRING SubsystemName,
+ IN PUNICODE_STRING ServiceName,
+ IN HANDLE ClientToken,
+ IN PPRIVILEGE_SET Privileges,
+ IN BOOLEAN AccessGranted
+ );
+
+NTSTATUS
+STDCALL
+ZwPrivilegedServiceAuditAlarm(
+ IN PUNICODE_STRING SubsystemName,
+ IN PUNICODE_STRING ServiceName,
+ IN HANDLE ClientToken,
+ IN PPRIVILEGE_SET Privileges,
+ IN BOOLEAN AccessGranted
+ );
+
+NTSTATUS
+STDCALL
+NtPrivilegeObjectAuditAlarm(
+ IN PUNICODE_STRING SubsystemName,
+ IN PVOID HandleId,
+ IN HANDLE ClientToken,
+ IN ULONG DesiredAccess,
+ IN PPRIVILEGE_SET Privileges,
+ IN BOOLEAN AccessGranted
+ );
+
+NTSTATUS
+STDCALL
+ZwPrivilegeObjectAuditAlarm(
+ IN PUNICODE_STRING SubsystemName,
+ IN PVOID HandleId,
+ IN HANDLE ClientToken,
+ IN ULONG DesiredAccess,
+ IN PPRIVILEGE_SET Privileges,
+ IN BOOLEAN AccessGranted
+ );
+
+/*
+ * FUNCTION: Entry point for native applications
+ * ARGUMENTS:
+ * Peb = Pointes to the Process Environment Block (PEB)
+ * REMARKS:
+ * Native applications should use this function instead of a main.
+ * Calling proces should terminate itself.
+ * RETURNS: Status
+ */
+VOID STDCALL
+NtProcessStartup(
+ IN PPEB Peb
+ );
+
+
+/*
+ * FUNCTION: Signals an event and resets it afterwards.
+ * ARGUMENTS:
+ * EventHandle = Handle to the event
+ * PulseCount = Number of times the action is repeated
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtPulseEvent(
+ IN HANDLE EventHandle,
+ IN PULONG PulseCount OPTIONAL
+ );
+
+NTSTATUS
+STDCALL
+ZwPulseEvent(
+ IN HANDLE EventHandle,
+ IN PULONG PulseCount OPTIONAL
+ );
+
+/*
+ * FUNCTION: Queries the attributes of a file
+ * ARGUMENTS:
+ * ObjectAttributes = Initialized attributes for the object
+ * Buffer = Caller supplies storage for the attributes
+ * RETURNS: Status
+ */
+
+NTSTATUS STDCALL
+NtQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
+ OUT PFILE_BASIC_INFORMATION FileInformation);
+
+NTSTATUS STDCALL
+ZwQueryAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
+ OUT PFILE_BASIC_INFORMATION FileInformation);
+
+/*
+ * FUNCTION: Queries the default locale id
+ * ARGUMENTS:
+ * UserProfile = Type of locale id
+ * TRUE: thread locale id
+ * FALSE: system locale id
+ * DefaultLocaleId = Caller supplies storage for the locale id
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtQueryDefaultLocale(
+ IN BOOLEAN UserProfile,
+ OUT PLCID DefaultLocaleId
+ );
+
+NTSTATUS
+STDCALL
+ZwQueryDefaultLocale(
+ IN BOOLEAN UserProfile,
+ OUT PLCID DefaultLocaleId
+ );
+
+/*
+ * FUNCTION: Queries a directory file.
+ * ARGUMENTS:
+ * FileHandle = Handle to a directory file
+ * EventHandle = Handle to the event signaled on completion
+ * ApcRoutine = Asynchroneous procedure callback, called on completion
+ * ApcContext = Argument to the apc.
+ * IoStatusBlock = Caller supplies storage for extended status information.
+ * FileInformation = Caller supplies storage for the resulting information.
+ *
+ * FileNameInformation FILE_NAMES_INFORMATION
+ * FileDirectoryInformation FILE_DIRECTORY_INFORMATION
+ * FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION
+ * FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION
+ *
+ * Length = Size of the storage supplied
+ * FileInformationClass = Indicates the type of information requested.
+ * ReturnSingleEntry = Specify true if caller only requests the first directory found.
+ * FileName = Initial directory name to query, that may contain wild cards.
+ * RestartScan = Number of times the action should be repeated
+ * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES,
+ * STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_BUFFER_OVERFLOW,
+ * STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ]
+ */
+
+NTSTATUS
+STDCALL
+NtQueryDirectoryFile(
+ IN HANDLE FileHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID FileInformation,
+ IN ULONG Length,
+ IN FILE_INFORMATION_CLASS FileInformationClass,
+ IN BOOLEAN ReturnSingleEntry,
+ IN PUNICODE_STRING FileName OPTIONAL,
+ IN BOOLEAN RestartScan
+ );
+
+NTSTATUS
+STDCALL
+ZwQueryDirectoryFile(
+ IN HANDLE FileHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID FileInformation,
+ IN ULONG Length,
+ IN FILE_INFORMATION_CLASS FileInformationClass,
+ IN BOOLEAN ReturnSingleEntry,
+ IN PUNICODE_STRING FileName OPTIONAL,
+ IN BOOLEAN RestartScan
+ );
+
+/*
+ * FUNCTION: Queries the extended attributes of a file
+ * ARGUMENTS:
+ * FileHandle = Handle to the event
+ * IoStatusBlock = Number of times the action is repeated
+ * Buffer
+ * Length
+ * ReturnSingleEntry
+ * EaList
+ * EaListLength
+ * EaIndex
+ * RestartScan
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtQueryEaFile(
+ IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID Buffer,
+ IN ULONG Length,
+ IN BOOLEAN ReturnSingleEntry,
+ IN PVOID EaList OPTIONAL,
+ IN ULONG EaListLength,
+ IN PULONG EaIndex OPTIONAL,
+ IN BOOLEAN RestartScan
+ );
+
+NTSTATUS
+STDCALL
+ZwQueryEaFile(
+ IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID Buffer,
+ IN ULONG Length,
+ IN BOOLEAN ReturnSingleEntry,
+ IN PVOID EaList OPTIONAL,
+ IN ULONG EaListLength,
+ IN PULONG EaIndex OPTIONAL,
+ IN BOOLEAN RestartScan
+ );
+
+/*
+ * FUNCTION: Queries an event
+ * ARGUMENTS:
+ * EventHandle = Handle to the event
+ * EventInformationClass = Index of the information structure
+
+ EventBasicInformation EVENT_BASIC_INFORMATION
+
+ * EventInformation = Caller supplies storage for the information structure
+ * EventInformationLength = Size of the information structure
+ * ReturnLength = Data written
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtQueryEvent(
+ IN HANDLE EventHandle,
+ IN EVENT_INFORMATION_CLASS EventInformationClass,
+ OUT PVOID EventInformation,
+ IN ULONG EventInformationLength,
+ OUT PULONG ReturnLength
+ );
+NTSTATUS
+STDCALL
+ZwQueryEvent(
+ IN HANDLE EventHandle,
+ IN EVENT_INFORMATION_CLASS EventInformationClass,
+ OUT PVOID EventInformation,
+ IN ULONG EventInformationLength,
+ OUT PULONG ReturnLength
+ );
+
+NTSTATUS STDCALL
+NtQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
+ OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation);
+
+NTSTATUS STDCALL
+ZwQueryFullAttributesFile(IN POBJECT_ATTRIBUTES ObjectAttributes,
+ OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation);
+
+/*
+ * FUNCTION: Queries the information of a file object.
+ * ARGUMENTS:
+ * FileHandle = Handle to the file object
+ * IoStatusBlock = Caller supplies storage for extended information
+ * on the current operation.
+ * FileInformation = Storage for the new file information
+ * Lenght = Size of the storage for the file information.
+ * FileInformationClass = Indicates which file information is queried
+
+ FileDirectoryInformation FILE_DIRECTORY_INFORMATION
+ FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION
+ FileBothDirectoryInformation FILE_BOTH_DIRECTORY_INFORMATION
+ FileBasicInformation FILE_BASIC_INFORMATION
+ FileStandardInformation FILE_STANDARD_INFORMATION
+ FileInternalInformation FILE_INTERNAL_INFORMATION
+ FileEaInformation FILE_EA_INFORMATION
+ FileAccessInformation FILE_ACCESS_INFORMATION
+ FileNameInformation FILE_NAME_INFORMATION
+ FileRenameInformation FILE_RENAME_INFORMATION
+ FileLinkInformation
+ FileNamesInformation FILE_NAMES_INFORMATION
+ FileDispositionInformation FILE_DISPOSITION_INFORMATION
+ FilePositionInformation FILE_POSITION_INFORMATION
+ FileFullEaInformation FILE_FULL_EA_INFORMATION
+ FileModeInformation FILE_MODE_INFORMATION
+ FileAlignmentInformation FILE_ALIGNMENT_INFORMATION
+ FileAllInformation FILE_ALL_INFORMATION
+
+ FileEndOfFileInformation FILE_END_OF_FILE_INFORMATION
+ FileAlternateNameInformation
+ FileStreamInformation FILE_STREAM_INFORMATION
+ FilePipeInformation
+ FilePipeLocalInformation
+ FilePipeRemoteInformation
+ FileMailslotQueryInformation
+ FileMailslotSetInformation
+ FileCompressionInformation FILE_COMPRESSION_INFORMATION
+ FileCopyOnWriteInformation
+ FileCompletionInformation IO_COMPLETION_CONTEXT
+ FileMoveClusterInformation
+ FileOleClassIdInformation
+ FileOleStateBitsInformation
+ FileNetworkOpenInformation FILE_NETWORK_OPEN_INFORMATION
+ FileObjectIdInformation
+ FileOleAllInformation
+ FileOleDirectoryInformation
+ FileContentIndexInformation
+ FileInheritContentIndexInformation
+ FileOleInformation
+ FileMaximumInformation
+
+ * REMARK:
+ * This procedure maps to the win32 GetShortPathName, GetLongPathName,
+ GetFullPathName, GetFileType, GetFileSize, GetFileTime functions.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtQueryInformationFile(
+ IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID FileInformation,
+ IN ULONG Length,
+ IN FILE_INFORMATION_CLASS FileInformationClass
+ );
+
+NTSTATUS
+STDCALL
+ZwQueryInformationFile(
+ HANDLE FileHandle,
+ PIO_STATUS_BLOCK IoStatusBlock,
+ PVOID FileInformation,
+ ULONG Length,
+ FILE_INFORMATION_CLASS FileInformationClass
+ );
+
+
+/*
+ * FUNCTION: Queries the information of a thread object.
+ * ARGUMENTS:
+ * ThreadHandle = Handle to the thread object
+ * ThreadInformationClass = Index to a certain information structure
+
+ ThreadBasicInformation THREAD_BASIC_INFORMATION
+ ThreadTimes KERNEL_USER_TIMES
+ ThreadPriority KPRIORITY
+ ThreadBasePriority KPRIORITY
+ ThreadAffinityMask KAFFINITY
+ ThreadImpersonationToken
+ ThreadDescriptorTableEntry
+ ThreadEnableAlignmentFaultFixup
+ ThreadEventPair
+ ThreadQuerySetWin32StartAddress
+ ThreadZeroTlsCell
+ ThreadPerformanceCount
+ ThreadAmILastThread BOOLEAN
+ ThreadIdealProcessor ULONG
+ ThreadPriorityBoost ULONG
+ MaxThreadInfoClass
+
+
+ * ThreadInformation = Caller supplies torage for the thread information
+ * ThreadInformationLength = Size of the thread information structure
+ * ReturnLength = Actual number of bytes written
+
+ * REMARK:
+ * This procedure maps to the win32 GetThreadTimes, GetThreadPriority,
+ GetThreadPriorityBoost functions.
+ * RETURNS: Status
+*/
+
+
+NTSTATUS
+STDCALL
+NtQueryInformationThread(
+ IN HANDLE ThreadHandle,
+ IN THREADINFOCLASS ThreadInformationClass,
+ OUT PVOID ThreadInformation,
+ IN ULONG ThreadInformationLength,
+ OUT PULONG ReturnLength
+ );
+
+
+NTSTATUS
+STDCALL
+NtQueryInformationToken(
+ IN HANDLE TokenHandle,
+ IN TOKEN_INFORMATION_CLASS TokenInformationClass,
+ OUT PVOID TokenInformation,
+ IN ULONG TokenInformationLength,
+ OUT PULONG ReturnLength
+ );
+
+NTSTATUS
+STDCALL
+ZwQueryInformationToken(
+ IN HANDLE TokenHandle,
+ IN TOKEN_INFORMATION_CLASS TokenInformationClass,
+ OUT PVOID TokenInformation,
+ IN ULONG TokenInformationLength,
+ OUT PULONG ReturnLength
+ );
+
+NTSTATUS
+STDCALL
+NtQueryIoCompletion(
+ IN HANDLE CompletionPort,
+ IN ULONG CompletionKey,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PULONG NumberOfBytesTransferred
+ );
+NTSTATUS
+STDCALL
+ZwQueryIoCompletion(
+ IN HANDLE CompletionPort,
+ IN ULONG CompletionKey,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PULONG NumberOfBytesTransferred
+ );
+
+
+/*
+ * FUNCTION: Queries the information of a registry key object.
+ * ARGUMENTS:
+ KeyHandle = Handle to a registry key
+ KeyInformationClass = Index to a certain information structure
+ KeyInformation = Caller supplies storage for resulting information
+ Length = Size of the supplied storage
+ ResultLength = Bytes written
+ */
+NTSTATUS
+STDCALL
+NtQueryKey(
+ IN HANDLE KeyHandle,
+ IN KEY_INFORMATION_CLASS KeyInformationClass,
+ OUT PVOID KeyInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+
+NTSTATUS
+STDCALL
+ZwQueryKey(
+ IN HANDLE KeyHandle,
+ IN KEY_INFORMATION_CLASS KeyInformationClass,
+ OUT PVOID KeyInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+
+
+// draft
+
+NTSTATUS
+STDCALL
+NtQueryMultipleValueKey(
+ IN HANDLE KeyHandle,
+ IN OUT PKEY_VALUE_ENTRY ValueList,
+ IN ULONG NumberOfValues,
+ OUT PVOID Buffer,
+ IN OUT PULONG Length,
+ OUT PULONG ReturnLength
+ );
+
+NTSTATUS
+STDCALL
+ZwQueryMultipleValueKey(
+ IN HANDLE KeyHandle,
+ IN OUT PKEY_VALUE_ENTRY ValueList,
+ IN ULONG NumberOfValues,
+ OUT PVOID Buffer,
+ IN OUT PULONG Length,
+ OUT PULONG ReturnLength
+ );
+
+/*
+ * FUNCTION: Queries the information of a mutant object.
+ * ARGUMENTS:
+ MutantHandle = Handle to a mutant
+ MutantInformationClass = Index to a certain information structure
+ MutantInformation = Caller supplies storage for resulting information
+ Length = Size of the supplied storage
+ ResultLength = Bytes written
+ */
+NTSTATUS
+STDCALL
+NtQueryMutant(
+ IN HANDLE MutantHandle,
+ IN CINT MutantInformationClass,
+ OUT PVOID MutantInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+
+NTSTATUS
+STDCALL
+ZwQueryMutant(
+ IN HANDLE MutantHandle,
+ IN CINT MutantInformationClass,
+ OUT PVOID MutantInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+
+/*
+ * FUNCTION: Queries the system ( high-resolution ) performance counter.
+ * ARGUMENTS:
+ * Counter = Performance counter
+ * Frequency = Performance frequency
+ * REMARKS:
+ This procedure queries a tick count faster than 10ms ( The resolution for Intel®-based CPUs is about 0.8 microseconds.)
+ This procedure maps to the win32 QueryPerformanceCounter, QueryPerformanceFrequency
+ * RETURNS: Status
+ *
+*/
+NTSTATUS
+STDCALL
+NtQueryPerformanceCounter(
+ IN PLARGE_INTEGER Counter,
+ IN PLARGE_INTEGER Frequency
+ );
+
+NTSTATUS
+STDCALL
+ZwQueryPerformanceCounter(
+ IN PLARGE_INTEGER Counter,
+ IN PLARGE_INTEGER Frequency
+ );
+
+/*
+ * FUNCTION: Queries the information of a semaphore.
+ * ARGUMENTS:
+ * SemaphoreHandle = Handle to the semaphore object
+ * SemaphoreInformationClass = Index to a certain information structure
+
+ SemaphoreBasicInformation SEMAPHORE_BASIC_INFORMATION
+
+ * SemaphoreInformation = Caller supplies storage for the semaphore information structure
+ * Length = Size of the infomation structure
+ */
+NTSTATUS
+STDCALL
+NtQuerySemaphore(
+ IN HANDLE SemaphoreHandle,
+ IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
+ OUT PVOID SemaphoreInformation,
+ IN ULONG Length,
+ OUT PULONG ReturnLength
+ );
+
+NTSTATUS
+STDCALL
+ZwQuerySemaphore(
+ IN HANDLE SemaphoreHandle,
+ IN SEMAPHORE_INFORMATION_CLASS SemaphoreInformationClass,
+ OUT PVOID SemaphoreInformation,
+ IN ULONG Length,
+ OUT PULONG ReturnLength
+ );
+
+
+/*
+ * FUNCTION: Queries the information of a symbolic link object.
+ * ARGUMENTS:
+ * SymbolicLinkHandle = Handle to the symbolic link object
+ * LinkTarget = resolved name of link
+ * DataWritten = size of the LinkName.
+ * RETURNS: Status
+ *
+*/
+NTSTATUS
+STDCALL
+NtQuerySymbolicLinkObject(
+ IN HANDLE SymLinkObjHandle,
+ OUT PUNICODE_STRING LinkTarget,
+ OUT PULONG DataWritten OPTIONAL
+ );
+
+NTSTATUS
+STDCALL
+ZwQuerySymbolicLinkObject(
+ IN HANDLE SymLinkObjHandle,
+ OUT PUNICODE_STRING LinkName,
+ OUT PULONG DataWritten OPTIONAL
+ );
+
+
+/*
+ * FUNCTION: Queries a system environment variable.
+ * ARGUMENTS:
+ * Name = Name of the variable
+ * Value (OUT) = value of the variable
+ * Length = size of the buffer
+ * ReturnLength = data written
+ * RETURNS: Status
+ *
+*/
+NTSTATUS
+STDCALL
+NtQuerySystemEnvironmentValue(
+ IN PUNICODE_STRING Name,
+ OUT PVOID Value,
+ ULONG Length,
+ PULONG ReturnLength
+ );
+
+NTSTATUS
+STDCALL
+ZwQuerySystemEnvironmentValue(
+ IN PUNICODE_STRING Name,
+ OUT PVOID Value,
+ ULONG Length,
+ PULONG ReturnLength
+ );
+
+
+/*
+ * FUNCTION: Queries the system information.
+ * ARGUMENTS:
+ * SystemInformationClass = Index to a certain information structure
+
+ SystemTimeAdjustmentInformation SYSTEM_TIME_ADJUSTMENT
+ SystemCacheInformation SYSTEM_CACHE_INFORMATION
+ SystemConfigurationInformation CONFIGURATION_INFORMATION
+
+ * SystemInformation = caller supplies storage for the information structure
+ * Length = size of the structure
+ ResultLength = Data written
+ * RETURNS: Status
+ *
+*/
+NTSTATUS
+STDCALL
+NtQuerySystemInformation(
+ IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
+ OUT PVOID SystemInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+
+NTSTATUS
+STDCALL
+ZwQuerySystemInformation(
+ IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
+ OUT PVOID SystemInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+
+/*
+ * FUNCTION: Queries information about a timer
+ * ARGUMENTS:
+ * TimerHandle = Handle to the timer
+ TimerValueInformationClass = Index to a certain information structure
+ TimerValueInformation = Caller supplies storage for the information structure
+ Length = Size of the information structure
+ ResultLength = Data written
+ * RETURNS: Status
+ *
+*/
+NTSTATUS
+STDCALL
+NtQueryTimer(
+ IN HANDLE TimerHandle,
+ IN CINT TimerInformationClass,
+ OUT PVOID TimerInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+NTSTATUS
+STDCALL
+ZwQueryTimer(
+ IN HANDLE TimerHandle,
+ IN CINT TimerInformationClass,
+ OUT PVOID TimerInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+
+/*
+ * FUNCTION: Queries the timer resolution
+ * ARGUMENTS:
+ * MinimumResolution (OUT) = Caller should supply storage for the resulting time.
+ Maximum Resolution (OUT) = Caller should supply storage for the resulting time.
+ ActualResolution (OUT) = Caller should supply storage for the resulting time.
+ * RETURNS: Status
+ *
+*/
+
+
+NTSTATUS
+STDCALL
+NtQueryTimerResolution (
+ OUT PULONG MinimumResolution,
+ OUT PULONG MaximumResolution,
+ OUT PULONG ActualResolution
+ );
+
+NTSTATUS
+STDCALL
+ZwQueryTimerResolution (
+ OUT PULONG MinimumResolution,
+ OUT PULONG MaximumResolution,
+ OUT PULONG ActualResolution
+ );
+
+/*
+ * FUNCTION: Queries a registry key value
+ * ARGUMENTS:
+ * KeyHandle = Handle to the registry key
+ ValueName = Name of the value in the registry key
+ KeyValueInformationClass = Index to a certain information structure
+
+ KeyValueBasicInformation = KEY_VALUE_BASIC_INFORMATION
+ KeyValueFullInformation = KEY_FULL_INFORMATION
+ KeyValuePartialInformation = KEY_VALUE_PARTIAL_INFORMATION
+
+ KeyValueInformation = Caller supplies storage for the information structure
+ Length = Size of the information structure
+ ResultLength = Data written
+ * RETURNS: Status
+ *
+*/
+NTSTATUS
+STDCALL
+NtQueryValueKey(
+ IN HANDLE KeyHandle,
+ IN PUNICODE_STRING ValueName,
+ IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
+ OUT PVOID KeyValueInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+
+NTSTATUS
+STDCALL
+ZwQueryValueKey(
+ IN HANDLE KeyHandle,
+ IN PUNICODE_STRING ValueName,
+ IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
+ OUT PVOID KeyValueInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+
+/*
+ * FUNCTION: Queries the volume information
+ * ARGUMENTS:
+ * FileHandle = Handle to a file object on the target volume
+ * IoStatusBlock = Caller should supply storage for additional status information
+ * ReturnLength = DataWritten
+ * FsInformation = Caller should supply storage for the information structure.
+ * Length = Size of the information structure
+ * FsInformationClass = Index to a information structure
+
+ FileFsVolumeInformation FILE_FS_VOLUME_INFORMATION
+ FileFsLabelInformation FILE_FS_LABEL_INFORMATION
+ FileFsSizeInformation FILE_FS_SIZE_INFORMATION
+ FileFsDeviceInformation FILE_FS_DEVICE_INFORMATION
+ FileFsAttributeInformation FILE_FS_ATTRIBUTE_INFORMATION
+ FileFsControlInformation
+ FileFsQuotaQueryInformation --
+ FileFsQuotaSetInformation --
+ FileFsMaximumInformation
+
+ * RETURNS: Status [ STATUS_SUCCESS | STATUS_INSUFFICIENT_RESOURCES | STATUS_INVALID_PARAMETER |
+ STATUS_INVALID_DEVICE_REQUEST | STATUS_BUFFER_OVERFLOW ]
+ *
+*/
+NTSTATUS
+STDCALL
+NtQueryVolumeInformationFile(
+ IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID FsInformation,
+ IN ULONG Length,
+ IN FS_INFORMATION_CLASS FsInformationClass
+ );
+
+NTSTATUS
+STDCALL
+ZwQueryVolumeInformationFile(
+ IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID FsInformation,
+ IN ULONG Length,
+ IN FS_INFORMATION_CLASS FsInformationClass
+ );
+// draft
+// FIXME: Should I specify if the apc is user or kernel mode somewhere ??
+/*
+ * FUNCTION: Queues a (user) apc to a thread.
+ * ARGUMENTS:
+ ThreadHandle = Thread to which the apc is queued.
+ ApcRoutine = Points to the apc routine
+ NormalContext = Argument to Apc Routine
+ * SystemArgument1 = Argument of the Apc Routine
+ SystemArgument2 = Argument of the Apc Routine
+ * REMARK: If the apc is queued against a thread of a different process than the calling thread
+ the apc routine should be specified in the address space of the queued thread's process.
+ * RETURNS: Status
+*/
+
+NTSTATUS
+STDCALL
+NtQueueApcThread(
+ HANDLE ThreadHandle,
+ PKNORMAL_ROUTINE ApcRoutine,
+ PVOID NormalContext,
+ PVOID SystemArgument1,
+ PVOID SystemArgument2);
+
+NTSTATUS
+STDCALL
+ZwQueueApcThread(
+ HANDLE ThreadHandle,
+ PKNORMAL_ROUTINE ApcRoutine,
+ PVOID NormalContext,
+ PVOID SystemArgument1,
+ PVOID SystemArgument2);
+
+
+/*
+ * FUNCTION: Raises an exception
+ * ARGUMENTS:
+ * ExceptionRecord = Structure specifying the exception
+ * Context = Context in which the excpetion is raised
+ * IsDebugger =
+ * RETURNS: Status
+ *
+*/
+
+NTSTATUS
+STDCALL
+NtRaiseException(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PCONTEXT Context,
+ IN BOOLEAN SearchFrames
+ );
+
+NTSTATUS
+STDCALL
+ZwRaiseException(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PCONTEXT Context,
+ IN BOOLEAN SearchFrames
+ );
+
+/*
+ * FUNCTION: Read a file
+ * ARGUMENTS:
+ * FileHandle = Handle of a file to read
+ * Event = This event is signalled when the read operation completes
+ * UserApcRoutine = Call back , if supplied Event should be NULL
+ * UserApcContext = Argument to the callback
+ * IoStatusBlock = Caller should supply storage for additional status information
+ * Buffer = Caller should supply storage to receive the information
+ * BufferLength = Size of the buffer
+ * ByteOffset = Offset to start reading the file
+ * Key = If a range is lock a matching key will allow the read to continue.
+ * RETURNS: Status
+ *
+ */
+
+NTSTATUS
+STDCALL
+NtReadFile(
+ IN HANDLE FileHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
+ IN PVOID UserApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ IN PLARGE_INTEGER ByteOffset OPTIONAL,
+ IN PULONG Key OPTIONAL
+ );
+
+NTSTATUS
+STDCALL
+ZwReadFile(
+ IN HANDLE FileHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
+ IN PVOID UserApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ IN PLARGE_INTEGER ByteOffset OPTIONAL,
+ IN PULONG Key OPTIONAL
+ );
+/*
+ * FUNCTION: Read a file using scattered io
+ * ARGUMENTS:
+ FileHandle = Handle of a file to read
+ Event = This event is signalled when the read operation completes
+ * UserApcRoutine = Call back , if supplied Event should be NULL
+ UserApcContext = Argument to the callback
+ IoStatusBlock = Caller should supply storage for additional status information
+ BufferDescription = Caller should supply storage to receive the information
+ BufferLength = Size of the buffer
+ ByteOffset = Offset to start reading the file
+ Key = Key = If a range is lock a matching key will allow the read to continue.
+ * RETURNS: Status
+ *
+*/
+NTSTATUS
+STDCALL
+NtReadFileScatter(
+ IN HANDLE FileHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
+ IN PVOID UserApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK UserIoStatusBlock,
+ IN FILE_SEGMENT_ELEMENT BufferDescription[],
+ IN ULONG BufferLength,
+ IN PLARGE_INTEGER ByteOffset,
+ IN PULONG Key OPTIONAL
+ );
+
+NTSTATUS
+STDCALL
+ZwReadFileScatter(
+ IN HANDLE FileHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
+ IN PVOID UserApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK UserIoStatusBlock,
+ IN FILE_SEGMENT_ELEMENT BufferDescription[],
+ IN ULONG BufferLength,
+ IN PLARGE_INTEGER ByteOffset,
+ IN PULONG Key OPTIONAL
+ );
+/*
+ * FUNCTION: Copies a range of virtual memory to a buffer
+ * ARGUMENTS:
+ * ProcessHandle = Specifies the process owning the virtual address space
+ * BaseAddress = Points to the address of virtual memory to start the read
+ * Buffer = Caller supplies storage to copy the virtual memory to.
+ * NumberOfBytesToRead = Limits the range to read
+ * NumberOfBytesRead = The actual number of bytes read.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtReadVirtualMemory(
+ IN HANDLE ProcessHandle,
+ IN PVOID BaseAddress,
+ OUT PVOID Buffer,
+ IN ULONG NumberOfBytesToRead,
+ OUT PULONG NumberOfBytesRead
+ );
+NTSTATUS
+STDCALL
+ZwReadVirtualMemory(
+ IN HANDLE ProcessHandle,
+ IN PVOID BaseAddress,
+ OUT PVOID Buffer,
+ IN ULONG NumberOfBytesToRead,
+ OUT PULONG NumberOfBytesRead
+ );
+
+
+/*
+ * FUNCTION: Debugger can register for thread termination
+ * ARGUMENTS:
+ * TerminationPort = Port on which the debugger likes to be notified.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtRegisterThreadTerminatePort(
+ HANDLE TerminationPort
+ );
+NTSTATUS
+STDCALL
+ZwRegisterThreadTerminatePort(
+ HANDLE TerminationPort
+ );
+
+/*
+ * FUNCTION: Releases a mutant
+ * ARGUMENTS:
+ * MutantHandle = Handle to the mutant
+ * ReleaseCount =
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtReleaseMutant(
+ IN HANDLE MutantHandle,
+ IN PULONG ReleaseCount OPTIONAL
+ );
+
+NTSTATUS
+STDCALL
+ZwReleaseMutant(
+ IN HANDLE MutantHandle,
+ IN PULONG ReleaseCount OPTIONAL
+ );
+
+/*
+ * FUNCTION: Releases a semaphore
+ * ARGUMENTS:
+ * SemaphoreHandle = Handle to the semaphore object
+ * ReleaseCount = Number to decrease the semaphore count
+ * PreviousCount = Previous semaphore count
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtReleaseSemaphore(
+ IN HANDLE SemaphoreHandle,
+ IN LONG ReleaseCount,
+ OUT PLONG PreviousCount
+ );
+
+NTSTATUS
+STDCALL
+ZwReleaseSemaphore(
+ IN HANDLE SemaphoreHandle,
+ IN LONG ReleaseCount,
+ OUT PLONG PreviousCount
+ );
+
+/*
+ * FUNCTION: Removes an io completion
+ * ARGUMENTS:
+ * CompletionPort (OUT) = Caller supplied storage for the resulting handle
+ * CompletionKey = Requested access to the key
+ * IoStatusBlock = Caller provides storage for extended status information
+ * CompletionStatus = Current status of the io operation.
+ * WaitTime = Time to wait if ..
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtRemoveIoCompletion(
+ IN HANDLE CompletionPort,
+ OUT PULONG CompletionKey,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PULONG CompletionStatus,
+ IN PLARGE_INTEGER WaitTime
+ );
+
+NTSTATUS
+STDCALL
+ZwRemoveIoCompletion(
+ IN HANDLE CompletionPort,
+ OUT PULONG CompletionKey,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PULONG CompletionStatus,
+ IN PLARGE_INTEGER WaitTime
+ );
+/*
+ * FUNCTION: Replaces one registry key with another
+ * ARGUMENTS:
+ * ObjectAttributes = Specifies the attributes of the key
+ * Key = Handle to the key
+ * ReplacedObjectAttributes = The function returns the old object attributes
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtReplaceKey(
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN HANDLE Key,
+ IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
+ );
+NTSTATUS
+STDCALL
+ZwReplaceKey(
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN HANDLE Key,
+ IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
+ );
+
+/*
+ * FUNCTION: Resets a event to a non signaled state
+ * ARGUMENTS:
+ * EventHandle = Handle to the event that should be reset
+ * NumberOfWaitingThreads = The number of threads released.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtResetEvent(
+ HANDLE EventHandle,
+ PULONG NumberOfWaitingThreads OPTIONAL
+ );
+NTSTATUS
+STDCALL
+ZwResetEvent(
+ HANDLE EventHandle,
+ PULONG NumberOfWaitingThreads OPTIONAL
+ );
+//draft
+NTSTATUS
+STDCALL
+NtRestoreKey(
+ HANDLE KeyHandle,
+ HANDLE FileHandle,
+ ULONG RestoreFlags
+ );
+
+NTSTATUS
+STDCALL
+ZwRestoreKey(
+ HANDLE KeyHandle,
+ HANDLE FileHandle,
+ ULONG RestoreFlags
+ );
+/*
+ * FUNCTION: Decrements a thread's resume count
+ * ARGUMENTS:
+ * ThreadHandle = Handle to the thread that should be resumed
+ * ResumeCount = The resulting resume count.
+ * REMARK:
+ * A thread is resumed if its suspend count is 0. This procedure maps to
+ * the win32 ResumeThread function. ( documentation about the the suspend count can be found here aswell )
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtResumeThread(
+ IN HANDLE ThreadHandle,
+ OUT PULONG SuspendCount
+ );
+NTSTATUS
+STDCALL
+ZwResumeThread(
+ IN HANDLE ThreadHandle,
+ OUT PULONG SuspendCount
+ );
+/*
+ * FUNCTION: Writes the content of a registry key to ascii file
+ * ARGUMENTS:
+ * KeyHandle = Handle to the key
+ * FileHandle = Handle of the file
+ * REMARKS:
+ This function maps to the Win32 RegSaveKey.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtSaveKey(
+ IN HANDLE KeyHandle,
+ IN HANDLE FileHandle
+ );
+NTSTATUS
+STDCALL
+ZwSaveKey(
+ IN HANDLE KeyHandle,
+ IN HANDLE FileHandle
+ );
+
+/*
+ * FUNCTION: Sets the context of a specified thread.
+ * ARGUMENTS:
+ * ThreadHandle = Handle to the thread
+ * Context = The processor context.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtSetContextThread(
+ IN HANDLE ThreadHandle,
+ IN PCONTEXT Context
+ );
+NTSTATUS
+STDCALL
+ZwSetContextThread(
+ IN HANDLE ThreadHandle,
+ IN PCONTEXT Context
+ );
+
+/*
+ * FUNCTION: Sets the default locale id
+ * ARGUMENTS:
+ * UserProfile = Type of locale id
+ * TRUE: thread locale id
+ * FALSE: system locale id
+ * DefaultLocaleId = Locale id
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtSetDefaultLocale(
+ IN BOOLEAN UserProfile,
+ IN LCID DefaultLocaleId
+ );
+
+NTSTATUS
+STDCALL
+ZwSetDefaultLocale(
+ IN BOOLEAN UserProfile,
+ IN LCID DefaultLocaleId
+ );
+
+/*
+ * FUNCTION: Sets the default hard error port
+ * ARGUMENTS:
+ * PortHandle = Handle to the port
+ * NOTE: The hard error port is used for first change exception handling
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtSetDefaultHardErrorPort(
+ IN HANDLE PortHandle
+ );
+NTSTATUS
+STDCALL
+ZwSetDefaultHardErrorPort(
+ IN HANDLE PortHandle
+ );
+
+/*
+ * FUNCTION: Sets the extended attributes of a file.
+ * ARGUMENTS:
+ * FileHandle = Handle to the file
+ * IoStatusBlock = Storage for a resulting status and information
+ * on the current operation.
+ * EaBuffer = Extended Attributes buffer.
+ * EaBufferSize = Size of the extended attributes buffer
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtSetEaFile(
+ IN HANDLE FileHandle,
+ IN PIO_STATUS_BLOCK IoStatusBlock,
+ PVOID EaBuffer,
+ ULONG EaBufferSize
+ );
+NTSTATUS
+STDCALL
+ZwSetEaFile(
+ IN HANDLE FileHandle,
+ IN PIO_STATUS_BLOCK IoStatusBlock,
+ PVOID EaBuffer,
+ ULONG EaBufferSize
+ );
+
+//FIXME: should I return the event state ?
+
+/*
+ * FUNCTION: Sets the event to a signalled state.
+ * ARGUMENTS:
+ * EventHandle = Handle to the event
+ * NumberOfThreadsReleased = The number of threads released
+ * REMARK:
+ * This procedure maps to the win32 SetEvent function.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtSetEvent(
+ IN HANDLE EventHandle,
+ PULONG NumberOfThreadsReleased
+ );
+
+NTSTATUS
+STDCALL
+ZwSetEvent(
+ IN HANDLE EventHandle,
+ PULONG NumberOfThreadsReleased
+ );
+
+/*
+ * FUNCTION: Sets the high part of an event pair
+ * ARGUMENTS:
+ EventPair = Handle to the event pair
+ * RETURNS: Status
+*/
+
+NTSTATUS
+STDCALL
+NtSetHighEventPair(
+ IN HANDLE EventPairHandle
+ );
+
+NTSTATUS
+STDCALL
+ZwSetHighEventPair(
+ IN HANDLE EventPairHandle
+ );
+/*
+ * FUNCTION: Sets the high part of an event pair and wait for the low part
+ * ARGUMENTS:
+ EventPair = Handle to the event pair
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetHighWaitLowEventPair(
+ IN HANDLE EventPairHandle
+ );
+NTSTATUS
+STDCALL
+ZwSetHighWaitLowEventPair(
+ IN HANDLE EventPairHandle
+ );
+
+/*
+ * FUNCTION: Sets the information of a file object.
+ * ARGUMENTS:
+ * FileHandle = Handle to the file object
+ * IoStatusBlock = Caller supplies storage for extended information
+ * on the current operation.
+ * FileInformation = Storage for the new file information
+ * Lenght = Size of the new file information.
+ * FileInformationClass = Indicates to a certain information structure
+
+ FileNameInformation FILE_NAME_INFORMATION
+ FileRenameInformation FILE_RENAME_INFORMATION
+ FileStreamInformation FILE_STREAM_INFORMATION
+ * FileCompletionInformation IO_COMPLETION_CONTEXT
+
+ * REMARK:
+ * This procedure maps to the win32 SetEndOfFile, SetFileAttributes,
+ * SetNamedPipeHandleState, SetMailslotInfo functions.
+ * RETURNS: Status
+ */
+
+
+NTSTATUS
+STDCALL
+NtSetInformationFile(
+ IN HANDLE FileHandle,
+ IN PIO_STATUS_BLOCK IoStatusBlock,
+ IN PVOID FileInformation,
+ IN ULONG Length,
+ IN FILE_INFORMATION_CLASS FileInformationClass
+ );
+NTSTATUS
+STDCALL
+ZwSetInformationFile(
+ IN HANDLE FileHandle,
+ IN PIO_STATUS_BLOCK IoStatusBlock,
+ IN PVOID FileInformation,
+ IN ULONG Length,
+ IN FILE_INFORMATION_CLASS FileInformationClass
+ );
+
+/*
+ * FUNCTION: Changes a set of thread specific parameters
+ * ARGUMENTS:
+ * ThreadHandle = Handle to the thread
+ * ThreadInformationClass = Index to the set of parameters to change.
+ * Can be one of the following values:
+ *
+ * ThreadBasicInformation THREAD_BASIC_INFORMATION
+ * ThreadPriority KPRIORITY //???
+ * ThreadBasePriority KPRIORITY
+ * ThreadAffinityMask KAFFINITY //??
+ * ThreadImpersonationToken ACCESS_TOKEN
+ * ThreadIdealProcessor ULONG
+ * ThreadPriorityBoost ULONG
+ *
+ * ThreadInformation = Caller supplies storage for parameters to set.
+ * ThreadInformationLength = Size of the storage supplied
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetInformationThread(
+ IN HANDLE ThreadHandle,
+ IN THREADINFOCLASS ThreadInformationClass,
+ IN PVOID ThreadInformation,
+ IN ULONG ThreadInformationLength
+ );
+NTSTATUS
+STDCALL
+ZwSetInformationThread(
+ IN HANDLE ThreadHandle,
+ IN THREADINFOCLASS ThreadInformationClass,
+ IN PVOID ThreadInformation,
+ IN ULONG ThreadInformationLength
+ );
+
+/*
+ * FUNCTION: Changes a set of token specific parameters
+ * ARGUMENTS:
+ * TokenHandle = Handle to the token
+ * TokenInformationClass = Index to a certain information structure.
+ * Can be one of the following values:
+ *
+ TokenUser TOKEN_USER
+ TokenGroups TOKEN_GROUPS
+ TokenPrivileges TOKEN_PRIVILEGES
+ TokenOwner TOKEN_OWNER
+ TokenPrimaryGroup TOKEN_PRIMARY_GROUP
+ TokenDefaultDacl TOKEN_DEFAULT_DACL
+ TokenSource TOKEN_SOURCE
+ TokenType TOKEN_TYPE
+ TokenImpersonationLevel TOKEN_IMPERSONATION_LEVEL
+ TokenStatistics TOKEN_STATISTICS
+ *
+ * TokenInformation = Caller supplies storage for information structure.
+ * TokenInformationLength = Size of the information structure
+ * RETURNS: Status
+*/
+
+NTSTATUS
+STDCALL
+NtSetInformationToken(
+ IN HANDLE TokenHandle,
+ IN TOKEN_INFORMATION_CLASS TokenInformationClass,
+ OUT PVOID TokenInformation,
+ IN ULONG TokenInformationLength
+ );
+
+NTSTATUS
+STDCALL
+ZwSetInformationToken(
+ IN HANDLE TokenHandle,
+ IN TOKEN_INFORMATION_CLASS TokenInformationClass,
+ OUT PVOID TokenInformation,
+ IN ULONG TokenInformationLength
+ );
+
+
+/*
+ * FUNCTION: Sets an io completion
+ * ARGUMENTS:
+ * CompletionPort =
+ * CompletionKey =
+ * IoStatusBlock =
+ * NumberOfBytesToTransfer =
+ * NumberOfBytesTransferred =
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetIoCompletion(
+ IN HANDLE CompletionPort,
+ IN ULONG CompletionKey,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG NumberOfBytesToTransfer,
+ OUT PULONG NumberOfBytesTransferred
+ );
+NTSTATUS
+STDCALL
+ZwSetIoCompletion(
+ IN HANDLE CompletionPort,
+ IN ULONG CompletionKey,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG NumberOfBytesToTransfer,
+ OUT PULONG NumberOfBytesTransferred
+ );
+
+/*
+ * FUNCTION: Set properties for profiling
+ * ARGUMENTS:
+ * Interval =
+ * ClockSource =
+ * RETURNS: Status
+ *
+ */
+
+NTSTATUS
+STDCALL
+NtSetIntervalProfile(
+ ULONG Interval,
+ KPROFILE_SOURCE ClockSource
+ );
+
+NTSTATUS
+STDCALL
+ZwSetIntervalProfile(
+ ULONG Interval,
+ KPROFILE_SOURCE ClockSource
+ );
+
+
+/*
+ * FUNCTION: Sets the low part of an event pair
+ * ARGUMENTS:
+ EventPair = Handle to the event pair
+ * RETURNS: Status
+*/
+
+NTSTATUS
+STDCALL
+NtSetLowEventPair(
+ HANDLE EventPair
+ );
+NTSTATUS
+STDCALL
+ZwSetLowEventPair(
+ HANDLE EventPair
+ );
+/*
+ * FUNCTION: Sets the low part of an event pair and wait for the high part
+ * ARGUMENTS:
+ EventPair = Handle to the event pair
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetLowWaitHighEventPair(
+ HANDLE EventPair
+ );
+NTSTATUS
+STDCALL
+ZwSetLowWaitHighEventPair(
+ HANDLE EventPair
+ );
+
+NTSTATUS
+STDCALL
+NtSetSecurityObject(
+ IN HANDLE Handle,
+ IN SECURITY_INFORMATION SecurityInformation,
+ IN PSECURITY_DESCRIPTOR SecurityDescriptor
+ );
+
+NTSTATUS
+STDCALL
+ZwSetSecurityObject(
+ IN HANDLE Handle,
+ IN SECURITY_INFORMATION SecurityInformation,
+ IN PSECURITY_DESCRIPTOR SecurityDescriptor
+ );
+
+
+/*
+ * FUNCTION: Sets a system environment variable
+ * ARGUMENTS:
+ * ValueName = Name of the environment variable
+ * Value = Value of the environment variable
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetSystemEnvironmentValue(
+ IN PUNICODE_STRING VariableName,
+ IN PUNICODE_STRING Value
+ );
+NTSTATUS
+STDCALL
+ZwSetSystemEnvironmentValue(
+ IN PUNICODE_STRING VariableName,
+ IN PUNICODE_STRING Value
+ );
+/*
+ * FUNCTION: Sets system parameters
+ * ARGUMENTS:
+ * SystemInformationClass = Index to a particular set of system parameters
+ * Can be one of the following values:
+ *
+ * SystemTimeAdjustmentInformation SYSTEM_TIME_ADJUSTMENT
+ *
+ * SystemInformation = Structure containing the parameters.
+ * SystemInformationLength = Size of the structure.
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetSystemInformation(
+ IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
+ IN PVOID SystemInformation,
+ IN ULONG SystemInformationLength
+ );
+
+NTSTATUS
+STDCALL
+ZwSetSystemInformation(
+ IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
+ IN PVOID SystemInformation,
+ IN ULONG SystemInformationLength
+ );
+
+/*
+ * FUNCTION: Sets the system time
+ * ARGUMENTS:
+ * SystemTime = Old System time
+ * NewSystemTime = New System time
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetSystemTime(
+ IN PLARGE_INTEGER SystemTime,
+ IN PLARGE_INTEGER NewSystemTime OPTIONAL
+ );
+NTSTATUS
+STDCALL
+ZwSetSystemTime(
+ IN PLARGE_INTEGER SystemTime,
+ IN PLARGE_INTEGER NewSystemTime OPTIONAL
+ );
+
+/*
+ * FUNCTION: Sets the frequency of the system timer
+ * ARGUMENTS:
+ * RequestedResolution =
+ * SetOrUnset =
+ * ActualResolution =
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetTimerResolution(
+ IN ULONG RequestedResolution,
+ IN BOOL SetOrUnset,
+ OUT PULONG ActualResolution
+ );
+NTSTATUS
+STDCALL
+ZwSetTimerResolution(
+ IN ULONG RequestedResolution,
+ IN BOOL SetOrUnset,
+ OUT PULONG ActualResolution
+ );
+
+/*
+ * FUNCTION: Sets the value of a registry key
+ * ARGUMENTS:
+ * KeyHandle = Handle to a registry key
+ * ValueName = Name of the value entry to change
+ * TitleIndex = pointer to a structure containing the new volume information
+ * Type = Type of the registry key. Can be one of the values:
+ * REG_BINARY Unspecified binary data
+ * REG_DWORD A 32 bit value
+ * REG_DWORD_LITTLE_ENDIAN Same as REG_DWORD
+ * REG_DWORD_BIG_ENDIAN A 32 bit value whose least significant byte is at the highest address
+ * REG_EXPAND_SZ A zero terminated wide character string with unexpanded environment variables ( "%PATH%" )
+ * REG_LINK A zero terminated wide character string referring to a symbolic link.
+ * REG_MULTI_SZ A series of zero-terminated strings including a additional trailing zero
+ * REG_NONE Unspecified type
+ * REG_SZ A wide character string ( zero terminated )
+ * REG_RESOURCE_LIST ??
+ * REG_RESOURCE_REQUIREMENTS_LIST ??
+ * REG_FULL_RESOURCE_DESCRIPTOR ??
+ * Data = Contains the data for the registry key.
+ * DataSize = size of the data.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtSetValueKey(
+ IN HANDLE KeyHandle,
+ IN PUNICODE_STRING ValueName,
+ IN ULONG TitleIndex OPTIONAL,
+ IN ULONG Type,
+ IN PVOID Data,
+ IN ULONG DataSize
+ );
+NTSTATUS
+STDCALL
+ZwSetValueKey(
+ IN HANDLE KeyHandle,
+ IN PUNICODE_STRING ValueName,
+ IN ULONG TitleIndex OPTIONAL,
+ IN ULONG Type,
+ IN PVOID Data,
+ IN ULONG DataSize
+ );
+
+/*
+ * FUNCTION: Sets the volume information.
+ * ARGUMENTS:
+ * FileHandle = Handle to the file
+ * IoStatusBlock = Caller should supply storage for additional status information
+ * VolumeInformation = pointer to a structure containing the new volume information
+ * Length = size of the structure.
+ * VolumeInformationClass = specifies the particular volume information to set
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtSetVolumeInformationFile(
+ IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN PVOID FsInformation,
+ IN ULONG Length,
+ IN FS_INFORMATION_CLASS FsInformationClass
+ );
+
+NTSTATUS
+STDCALL
+ZwSetVolumeInformationFile(
+ IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN PVOID FsInformation,
+ IN ULONG Length,
+ IN FS_INFORMATION_CLASS FsInformationClass
+ );
+
+/*
+ * FUNCTION: Shuts the system down
+ * ARGUMENTS:
+ * Action = Specifies the type of shutdown, it can be one of the following values:
+ * ShutdownNoReboot, ShutdownReboot, ShutdownPowerOff
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtShutdownSystem(
+ IN SHUTDOWN_ACTION Action
+ );
+
+NTSTATUS
+STDCALL
+ZwShutdownSystem(
+ IN SHUTDOWN_ACTION Action
+ );
+
+
+/* --- PROFILING --- */
+
+/*
+ * FUNCTION: Starts profiling
+ * ARGUMENTS:
+ * ProfileHandle = Handle to the profile
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtStartProfile(
+ HANDLE ProfileHandle
+ );
+
+NTSTATUS
+STDCALL
+ZwStartProfile(
+ HANDLE ProfileHandle
+ );
+
+/*
+ * FUNCTION: Stops profiling
+ * ARGUMENTS:
+ * ProfileHandle = Handle to the profile
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtStopProfile(
+ HANDLE ProfileHandle
+ );
+
+NTSTATUS
+STDCALL
+ZwStopProfile(
+ HANDLE ProfileHandle
+ );
+
+/* --- PROCESS MANAGEMENT --- */
+
+//--NtSystemDebugControl
+/*
+ * FUNCTION: Terminates the execution of a process.
+ * ARGUMENTS:
+ * ThreadHandle = Handle to the process
+ * ExitStatus = The exit status of the process to terminate with.
+ * REMARKS
+ Native applications should kill themselves using this function.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtTerminateProcess(
+ IN HANDLE ProcessHandle ,
+ IN NTSTATUS ExitStatus
+ );
+NTSTATUS
+STDCALL
+ZwTerminateProcess(
+ IN HANDLE ProcessHandle ,
+ IN NTSTATUS ExitStatus
+ );
+
+/* --- DEVICE DRIVER CONTROL --- */
+
+/*
+ * FUNCTION: Unloads a driver.
+ * ARGUMENTS:
+ * DriverServiceName = Name of the driver to unload
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtUnloadDriver(
+ IN PUNICODE_STRING DriverServiceName
+ );
+NTSTATUS
+STDCALL
+ZwUnloadDriver(
+ IN PUNICODE_STRING DriverServiceName
+ );
+
+/* --- VIRTUAL MEMORY MANAGEMENT --- */
+
+/*
+ * FUNCTION: Writes a range of virtual memory
+ * ARGUMENTS:
+ * ProcessHandle = The handle to the process owning the address space.
+ * BaseAddress = The points to the address to write to
+ * Buffer = Pointer to the buffer to write
+ * NumberOfBytesToWrite = Offset to the upper boundary to write
+ * NumberOfBytesWritten = Total bytes written
+ * REMARKS:
+ * This function maps to the win32 WriteProcessMemory
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtWriteVirtualMemory(
+ IN HANDLE ProcessHandle,
+ IN PVOID BaseAddress,
+ IN PVOID Buffer,
+ IN ULONG NumberOfBytesToWrite,
+ OUT PULONG NumberOfBytesWritten
+ );
+
+NTSTATUS
+STDCALL
+ZwWriteVirtualMemory(
+ IN HANDLE ProcessHandle,
+ IN PVOID BaseAddress,
+ IN PVOID Buffer,
+ IN ULONG NumberOfBytesToWrite,
+ OUT PULONG NumberOfBytesWritten
+ );
+
+/*
+ * FUNCTION: Unmaps a piece of virtual memory backed by a file.
+ * ARGUMENTS:
+ * ProcessHandle = Handle to the process
+ * BaseAddress = The address where the mapping begins
+ * REMARK:
+ This procedure maps to the win32 UnMapViewOfFile
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtUnmapViewOfSection(
+ IN HANDLE ProcessHandle,
+ IN PVOID BaseAddress
+ );
+NTSTATUS
+STDCALL
+ZwUnmapViewOfSection(
+ IN HANDLE ProcessHandle,
+ IN PVOID BaseAddress
+ );
+
+/* --- OBJECT SYNCHRONIZATION --- */
+
+/*
+ * FUNCTION: Signals an object and wait for an other one.
+ * ARGUMENTS:
+ * SignalObject = Handle to the object that should be signaled
+ * WaitObject = Handle to the object that should be waited for
+ * Alertable = True if the wait is alertable
+ * Time = The time to wait
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtSignalAndWaitForSingleObject(
+ IN HANDLE SignalObject,
+ IN HANDLE WaitObject,
+ IN BOOLEAN Alertable,
+ IN PLARGE_INTEGER Time
+ );
+
+NTSTATUS
+STDCALL
+NtSignalAndWaitForSingleObject(
+ IN HANDLE SignalObject,
+ IN HANDLE WaitObject,
+ IN BOOLEAN Alertable,
+ IN PLARGE_INTEGER Time
+ );
+
+/*
+ * FUNCTION: Waits for an object to become signalled.
+ * ARGUMENTS:
+ * Object = The object handle
+ * Alertable = If true the wait is alertable.
+ * Time = The maximum wait time.
+ * REMARKS:
+ * This function maps to the win32 WaitForSingleObjectEx.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtWaitForSingleObject (
+ IN HANDLE Object,
+ IN BOOLEAN Alertable,
+ IN PLARGE_INTEGER Time
+ );
+
+NTSTATUS
+STDCALL
+ZwWaitForSingleObject (
+ IN HANDLE Object,
+ IN BOOLEAN Alertable,
+ IN PLARGE_INTEGER Time
+ );
+
+/* --- EVENT PAIR OBJECT --- */
+
+/*
+ * FUNCTION: Waits for the high part of an eventpair to become signalled
+ * ARGUMENTS:
+ * EventPairHandle = Handle to the event pair.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtWaitHighEventPair(
+ IN HANDLE EventPairHandle
+ );
+
+NTSTATUS
+STDCALL
+ZwWaitHighEventPair(
+ IN HANDLE EventPairHandle
+ );
+
+/*
+ * FUNCTION: Waits for the low part of an eventpair to become signalled
+ * ARGUMENTS:
+ * EventPairHandle = Handle to the event pair.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtWaitLowEventPair(
+ IN HANDLE EventPairHandle
+ );
+
+NTSTATUS
+STDCALL
+ZwWaitLowEventPair(
+ IN HANDLE EventPairHandle
+ );
+
+/* --- FILE MANAGEMENT --- */
+
+/*
+ * FUNCTION: Unlocks a range of bytes in a file.
+ * ARGUMENTS:
+ * FileHandle = Handle to the file
+ * IoStatusBlock = Caller should supply storage for a structure containing
+ * the completion status and information about the requested unlock operation.
+ The information field is set to the number of bytes unlocked.
+ * ByteOffset = Offset to start the range of bytes to unlock
+ * Length = Number of bytes to unlock.
+ * Key = Special value to enable other threads to unlock a file than the
+ thread that locked the file. The key supplied must match with the one obtained
+ in a previous call to NtLockFile.
+ * REMARK:
+ This procedure maps to the win32 procedure UnlockFileEx. STATUS_PENDING is returned if the lock could
+ not be obtained immediately, the device queue is busy and the IRP is queued.
+ * RETURNS: Status [ STATUS_SUCCESS | STATUS_PENDING | STATUS_ACCESS_DENIED | STATUS_INSUFFICIENT_RESOURCES |
+ STATUS_INVALID_PARAMETER | STATUS_INVALID_DEVICE_REQUEST | STATUS_RANGE_NOT_LOCKED ]
+ */
+NTSTATUS
+STDCALL
+NtUnlockFile(
+ IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN PLARGE_INTEGER ByteOffset,
+ IN PLARGE_INTEGER Lenght,
+ OUT PULONG Key OPTIONAL
+ );
+NTSTATUS
+STDCALL
+ZwUnlockFile(
+ IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN PLARGE_INTEGER ByteOffset,
+ IN PLARGE_INTEGER Lenght,
+ OUT PULONG Key OPTIONAL
+ );
+
+/*
+ * FUNCTION: Writes data to a file
+ * ARGUMENTS:
+ * FileHandle = The handle a file ( from NtCreateFile )
+ * Event = Specifies a event that will become signalled when the write operation completes.
+ * ApcRoutine = Asynchroneous Procedure Callback [ Should not be used by device drivers ]
+ * ApcContext = Argument to the Apc Routine
+ * IoStatusBlock = Caller should supply storage for a structure containing the completion status and information about the requested write operation.
+ * Buffer = Caller should supply storage for a buffer that will contain the information to be written to file.
+ * Length = Size in bytest of the buffer
+ * ByteOffset = Points to a file offset. If a combination of Length and BytesOfSet is past the end-of-file mark the file will be enlarged.
+ * BytesOffset is ignored if the file is created with FILE_APPEND_DATA in the DesiredAccess. BytesOffset is also ignored if
+ * the file is created with CreateOptions flags FILE_SYNCHRONOUS_IO_ALERT or FILE_SYNCHRONOUS_IO_NONALERT set, in that case a offset
+ * should be created by specifying FILE_USE_FILE_POINTER_POSITION.
+ * Key = Unused
+ * REMARKS:
+ * This function maps to the win32 WriteFile.
+ * Callers to NtWriteFile should run at IRQL PASSIVE_LEVEL.
+ * RETURNS: Status [ STATUS_SUCCESS | STATUS_PENDING | STATUS_ACCESS_DENIED | STATUS_INSUFFICIENT_RESOURCES
+ STATUS_INVALID_PARAMETER | STATUS_INVALID_DEVICE_REQUEST | STATUS_FILE_LOCK_CONFLICT ]
+ */
+NTSTATUS
+STDCALL
+NtWriteFile(
+ IN HANDLE FileHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ IN PLARGE_INTEGER ByteOffset,
+ IN PULONG Key OPTIONAL
+ );
+
+NTSTATUS
+STDCALL
+ZwWriteFile(
+ IN HANDLE FileHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ IN PLARGE_INTEGER ByteOffset ,
+ IN PULONG Key OPTIONAL
+ );
+
+/*
+ * FUNCTION: Writes a file
+ * ARGUMENTS:
+ * FileHandle = The handle of the file
+ * Event =
+ * ApcRoutine = Asynchroneous Procedure Callback [ Should not be used by device drivers ]
+ * ApcContext = Argument to the Apc Routine
+ * IoStatusBlock = Caller should supply storage for a structure containing the completion status and information about the requested write operation.
+ * BufferDescription = Caller should supply storage for a buffer that will contain the information to be written to file.
+ * BufferLength = Size in bytest of the buffer
+ * ByteOffset = Points to a file offset. If a combination of Length and BytesOfSet is past the end-of-file mark the file will be enlarged.
+ * BytesOffset is ignored if the file is created with FILE_APPEND_DATA in the DesiredAccess. BytesOffset is also ignored if
+ * the file is created with CreateOptions flags FILE_SYNCHRONOUS_IO_ALERT or FILE_SYNCHRONOUS_IO_NONALERT set, in that case a offset
+ * should be created by specifying FILE_USE_FILE_POINTER_POSITION. Use FILE_WRITE_TO_END_OF_FILE to write to the EOF.
+ * Key = If a matching key [ a key provided at NtLockFile ] is provided the write operation will continue even if a byte range is locked.
+ * REMARKS:
+ * This function maps to the win32 WriteFile.
+ * Callers to NtWriteFile should run at IRQL PASSIVE_LEVEL.
+ * RETURNS: Status [ STATUS_SUCCESS | STATUS_PENDING | STATUS_ACCESS_DENIED | STATUS_INSUFFICIENT_RESOURCES
+ STATUS_INVALID_PARAMETER | STATUS_INVALID_DEVICE_REQUEST | STATUS_FILE_LOCK_CONFLICT ]
+ */
+
+NTSTATUS
+STDCALL
+NtWriteFileGather(
+ IN HANDLE FileHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN FILE_SEGMENT_ELEMENT BufferDescription[],
+ IN ULONG BufferLength,
+ IN PLARGE_INTEGER ByteOffset,
+ IN PULONG Key OPTIONAL
+ );
+
+NTSTATUS
+STDCALL
+ZwWriteFileGather(
+ IN HANDLE FileHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN FILE_SEGMENT_ELEMENT BufferDescription[],
+ IN ULONG BufferLength,
+ IN PLARGE_INTEGER ByteOffset,
+ IN PULONG Key OPTIONAL
+ );
+
+
+/* --- THREAD MANAGEMENT --- */
+
+/*
+ * FUNCTION: Increments a thread's resume count
+ * ARGUMENTS:
+ * ThreadHandle = Handle to the thread that should be resumed
+ * PreviousSuspendCount = The resulting/previous suspend count.
+ * REMARK:
+ * A thread will be suspended if its suspend count is greater than 0. This procedure maps to
+ * the win32 SuspendThread function. ( documentation about the the suspend count can be found here aswell )
+ * The suspend count is not increased if it is greater than MAXIMUM_SUSPEND_COUNT.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtSuspendThread(
+ IN HANDLE ThreadHandle,
+ IN PULONG PreviousSuspendCount
+ );
+
+NTSTATUS
+STDCALL
+ZwSuspendThread(
+ IN HANDLE ThreadHandle,
+ IN PULONG PreviousSuspendCount
+ );
+
+/*
+ * FUNCTION: Terminates the execution of a thread.
+ * ARGUMENTS:
+ * ThreadHandle = Handle to the thread
+ * ExitStatus = The exit status of the thread to terminate with.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtTerminateThread(
+ IN HANDLE ThreadHandle ,
+ IN NTSTATUS ExitStatus
+ );
+NTSTATUS
+STDCALL
+ZwTerminateThread(
+ IN HANDLE ThreadHandle ,
+ IN NTSTATUS ExitStatus
+ );
+/*
+ * FUNCTION: Tests to see if there are any pending alerts for the calling thread
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtTestAlert(
+ VOID
+ );
+NTSTATUS
+STDCALL
+ZwTestAlert(
+ VOID
+ );
+
+/*
+ * FUNCTION: Yields the callers thread.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtYieldExecution(
+ VOID
+ );
+
+NTSTATUS
+STDCALL
+ZwYieldExecution(
+ VOID
+ );
+
+/* --- PLUG AND PLAY --- */
+
+NTSTATUS
+STDCALL
+NtPlugPlayControl (
+ VOID
+ );
+
+NTSTATUS
+STDCALL
+NtGetPlugPlayEvent (
+ VOID
+ );
+
+/* --- POWER MANAGEMENT --- */
+
+NTSTATUS STDCALL
+NtSetSystemPowerState(IN POWER_ACTION SystemAction,
+ IN SYSTEM_POWER_STATE MinSystemState,
+ IN ULONG Flags);
+
+/* --- DEBUG SUBSYSTEM --- */
+
+NTSTATUS STDCALL
+NtSystemDebugControl(DEBUG_CONTROL_CODE ControlCode,
+ PVOID InputBuffer,
+ ULONG InputBufferLength,
+ PVOID OutputBuffer,
+ ULONG OutputBufferLength,
+ PULONG ReturnLength);
+
+/* --- VIRTUAL DOS MACHINE (VDM) --- */
+
+NTSTATUS
+STDCALL
+NtVdmControl (ULONG ControlCode, PVOID ControlData);
+
+
+/* --- WIN32 --- */
+
+NTSTATUS STDCALL
+NtW32Call(IN ULONG RoutineIndex,
+ IN PVOID Argument,
+ IN ULONG ArgumentLength,
+ OUT PVOID* Result OPTIONAL,
+ OUT PULONG ResultLength OPTIONAL);
+
+/* --- CHANNELS --- */
+
+NTSTATUS
+STDCALL
+NtCreateChannel (
+ VOID
+ );
+
+NTSTATUS
+STDCALL
+NtListenChannel (
+ VOID
+ );
+
+NTSTATUS
+STDCALL
+NtOpenChannel (
+ VOID
+ );
+
+NTSTATUS
+STDCALL
+NtReplyWaitSendChannel (
+ VOID
+ );
+
+NTSTATUS
+STDCALL
+NtSendWaitReplyChannel (
+ VOID
+ );
+
+NTSTATUS
+STDCALL
+NtSetContextChannel (
+ VOID
+ );
+
+/* --- MISCELLANEA --- */
+
+//NTSTATUS STDCALL NtSetLdtEntries(VOID);
+NTSTATUS
+STDCALL
+NtSetLdtEntries (
+ HANDLE Thread,
+ ULONG FirstEntry,
+ PULONG Entries
+ );
+
+NTSTATUS
+STDCALL
+NtQueryOleDirectoryFile (
+ VOID
+ );
+
+/*
+ * FUNCTION: Checks a clients access rights to a object
+ * ARGUMENTS:
+ * SecurityDescriptor = Security information against which the access is checked
+ * ClientToken = Represents a client
+ * DesiredAcces =
+ * GenericMapping =
+ * PrivilegeSet =
+ * ReturnLength = Bytes written
+ * GrantedAccess =
+ * AccessStatus = Indicates if the ClientToken allows the requested access
+ * REMARKS: The arguments map to the win32 AccessCheck
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtAccessCheck(
+ IN PSECURITY_DESCRIPTOR SecurityDescriptor,
+ IN HANDLE ClientToken,
+ IN ACCESS_MASK DesiredAcces,
+ IN PGENERIC_MAPPING GenericMapping,
+ OUT PPRIVILEGE_SET PrivilegeSet,
+ OUT PULONG ReturnLength,
+ OUT PULONG GrantedAccess,
+ OUT PBOOLEAN AccessStatus
+ );
+
+NTSTATUS
+STDCALL
+ZwAccessCheck(
+ IN PSECURITY_DESCRIPTOR SecurityDescriptor,
+ IN HANDLE ClientToken,
+ IN ACCESS_MASK DesiredAcces,
+ IN PGENERIC_MAPPING GenericMapping,
+ OUT PPRIVILEGE_SET PrivilegeSet,
+ OUT PULONG ReturnLength,
+ OUT PULONG GrantedAccess,
+ OUT PBOOLEAN AccessStatus
+ );
+
+NTSTATUS
+STDCALL
+RtlOpenCurrentUser(
+ IN ACCESS_MASK DesiredAccess,
+ OUT PHANDLE KeyHandle);
+
+
+#ifndef __USE_W32API
+
+/*
+ * FUNCTION: Continues a thread with the specified context
+ * ARGUMENTS:
+ * Context = Specifies the processor context
+ * IrqLevel = Specifies the Interupt Request Level to continue with. Can
+ * be PASSIVE_LEVEL or APC_LEVEL
+ * REMARKS
+ * NtContinue can be used to continue after an exception or apc.
+ * RETURNS: Status
+ */
+//FIXME This function might need another parameter
+
+NTSTATUS
+STDCALL
+NtContinue(
+ IN PCONTEXT Context,
+ IN BOOLEAN TestAlert
+ );
+
+NTSTATUS STDCALL ZwContinue(IN PCONTEXT Context, IN CINT IrqLevel);
+
+/*
+ * FUNCTION: Retrieves the system time
+ * ARGUMENTS:
+ * CurrentTime (OUT) = Caller should supply storage for the resulting time.
+ * RETURNS: Status
+ *
+*/
+
+NTSTATUS
+STDCALL
+NtQuerySystemTime (
+ OUT TIME *CurrentTime
+ );
+
+NTSTATUS
+STDCALL
+ZwQuerySystemTime (
+ OUT TIME *CurrentTime
+ );
+
+/*
+ * FUNCTION: Loads a registry key.
+ * ARGUMENTS:
+ * KeyHandle = Handle to the registry key
+ * ObjectAttributes = ???
+ * Unknown3 = ???
+ * REMARK:
+ * This procedure maps to the win32 procedure RegLoadKey
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtLoadKey2 (
+ PHANDLE KeyHandle,
+ POBJECT_ATTRIBUTES ObjectAttributes,
+ ULONG Unknown3
+ );
+NTSTATUS
+STDCALL
+ZwLoadKey2 (
+ PHANDLE KeyHandle,
+ POBJECT_ATTRIBUTES ObjectAttributes,
+ ULONG Unknown3
+ );
+
+/*
+ * FUNCTION: Copies a handle from one process space to another
+ * ARGUMENTS:
+ * SourceProcessHandle = The source process owning the handle. The source process should have opened
+ * the SourceHandle with PROCESS_DUP_HANDLE access.
+ * SourceHandle = The handle to the object.
+ * TargetProcessHandle = The destination process owning the handle
+ * TargetHandle (OUT) = Caller should supply storage for the duplicated handle.
+ * DesiredAccess = The desired access to the handle.
+ * InheritHandle = Indicates wheter the new handle will be inheritable or not.
+ * Options = Specifies special actions upon duplicating the handle. Can be
+ * one of the values DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS.
+ * DUPLICATE_CLOSE_SOURCE specifies that the source handle should be
+ * closed after duplicating. DUPLICATE_SAME_ACCESS specifies to ignore
+ * the DesiredAccess paramter and just grant the same access to the new
+ * handle.
+ * RETURNS: Status
+ * REMARKS: This function maps to the win32 DuplicateHandle.
+ */
+
+NTSTATUS
+STDCALL
+NtDuplicateObject(
+ IN HANDLE SourceProcessHandle,
+ IN HANDLE SourceHandle,
+ IN HANDLE TargetProcessHandle,
+ OUT PHANDLE TargetHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN BOOLEAN InheritHandle,
+ IN ULONG Options
+ );
+
+NTSTATUS
+STDCALL
+ZwDuplicateObject(
+ IN HANDLE SourceProcessHandle,
+ IN PHANDLE SourceHandle,
+ IN HANDLE TargetProcessHandle,
+ OUT PHANDLE TargetHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN BOOLEAN InheritHandle,
+ IN ULONG Options
+ );
+
+/*
+ * FUNCTION: Checks a clients access rights to a object and issues a audit a alarm. ( it logs the access )
+ * ARGUMENTS:
+ * SubsystemName = Specifies the name of the subsystem, can be "WIN32" or "DEBUG"
+ * ObjectHandle =
+ * ObjectAttributes =
+ * DesiredAcces =
+ * GenericMapping =
+ * ObjectCreation =
+ * GrantedAccess =
+ * AccessStatus =
+ * GenerateOnClose =
+ * REMARKS: The arguments map to the win32 AccessCheck
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtAccessCheckAndAuditAlarm(
+ IN PUNICODE_STRING SubsystemName,
+ IN PHANDLE ObjectHandle,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN ACCESS_MASK DesiredAccess,
+ IN PGENERIC_MAPPING GenericMapping,
+ IN BOOLEAN ObjectCreation,
+ OUT PULONG GrantedAccess,
+ OUT PBOOLEAN AccessStatus,
+ OUT PBOOLEAN GenerateOnClose
+ );
+
+NTSTATUS
+STDCALL
+ZwAccessCheckAndAuditAlarm(
+ IN PUNICODE_STRING SubsystemName,
+ IN PHANDLE ObjectHandle,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN ACCESS_MASK DesiredAccess,
+ IN PGENERIC_MAPPING GenericMapping,
+ IN BOOLEAN ObjectCreation,
+ OUT PULONG GrantedAccess,
+ OUT PBOOLEAN AccessStatus,
+ OUT PBOOLEAN GenerateOnClose
+ );
+
+/*
+ * FUNCTION: Adds an atom to the global atom table
+ * ARGUMENTS:
+ * AtomString = The string to add to the atom table.
+ * Atom (OUT) = Caller supplies storage for the resulting atom.
+ * REMARKS: The arguments map to the win32 add GlobalAddAtom.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtAddAtom(
+ IN PWSTR AtomName,
+ IN OUT PRTL_ATOM Atom
+ );
+
+
+NTSTATUS
+STDCALL
+ZwAddAtom(
+ IN PWSTR AtomName,
+ IN OUT PRTL_ATOM Atom
+ );
+
+NTSTATUS
+STDCALL
+NtAllocateUuids(
+ PULARGE_INTEGER Time,
+ PULONG Range,
+ PULONG Sequence
+ );
+
+NTSTATUS
+STDCALL
+ZwAllocateUuids(
+ PULARGE_INTEGER Time,
+ PULONG Range,
+ PULONG Sequence
+ );
+
+/*
+ * FUNCTION: Cancels a timer
+ * ARGUMENTS:
+ * TimerHandle = Handle to the timer
+ * CurrentState = Specifies the state of the timer when cancelled.
+ * REMARKS:
+ * The arguments to this function map to the function CancelWaitableTimer.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtCancelTimer(
+ IN HANDLE TimerHandle,
+ OUT PBOOLEAN CurrentState OPTIONAL
+ );
+
+NTSTATUS
+STDCALL
+ZwCancelTimer(
+ IN HANDLE TimerHandle,
+ OUT ULONG ElapsedTime
+ );
+
+/*
+ * FUNCTION: Creates a paging file.
+ * ARGUMENTS:
+ * FileName = Name of the pagefile
+ * InitialSize = Specifies the initial size in bytes
+ * MaximumSize = Specifies the maximum size in bytes
+ * Reserved = Reserved for future use
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtCreatePagingFile(
+ IN PUNICODE_STRING FileName,
+ IN PLARGE_INTEGER InitialSize,
+ IN PLARGE_INTEGER MaxiumSize,
+ IN ULONG Reserved
+ );
+
+NTSTATUS
+STDCALL
+ZwCreatePagingFile(
+ IN PUNICODE_STRING FileName,
+ IN PLARGE_INTEGER InitialSize,
+ IN PLARGE_INTEGER MaxiumSize,
+ IN ULONG Reserved
+ );
+
+/*
+ * FUNCTION: Creates a user mode thread
+ * ARGUMENTS:
+ * ThreadHandle (OUT) = Caller supplied storage for the resulting handle
+ * DesiredAccess = Specifies the allowed or desired access to the thread.
+ * ObjectAttributes = Initialized attributes for the object.
+ * ProcessHandle = Handle to the threads parent process.
+ * ClientId (OUT) = Caller supplies storage for returned process id and thread id.
+ * ThreadContext = Initial processor context for the thread.
+ * InitialTeb = Initial user mode stack context for the thread.
+ * CreateSuspended = Specifies if the thread is ready for scheduling
+ * REMARKS:
+ * This function maps to the win32 function CreateThread.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtCreateThread(
+ OUT PHANDLE ThreadHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN HANDLE ProcessHandle,
+ OUT PCLIENT_ID ClientId,
+ IN PCONTEXT ThreadContext,
+ IN PINITIAL_TEB InitialTeb,
+ IN BOOLEAN CreateSuspended
+ );
+
+NTSTATUS
+STDCALL
+ZwCreateThread(
+ OUT PHANDLE ThreadHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
+ IN HANDLE ProcessHandle,
+ OUT PCLIENT_ID ClientId,
+ IN PCONTEXT ThreadContext,
+ IN PINITIAL_TEB InitialTeb,
+ IN BOOLEAN CreateSuspended
+ );
+
+NTSTATUS
+STDCALL
+NtDuplicateToken(
+ IN HANDLE ExistingToken,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
+ IN TOKEN_TYPE TokenType,
+ OUT PHANDLE NewToken
+ );
+
+NTSTATUS
+STDCALL
+ZwDuplicateToken(
+ IN HANDLE ExistingToken,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
+ IN TOKEN_TYPE TokenType,
+ OUT PHANDLE NewToken
+ );
+
+/*
+ * FUNCTION: Finds a atom
+ * ARGUMENTS:
+ * AtomName = Name to search for.
+ * Atom = Caller supplies storage for the resulting atom
+ * RETURNS: Status
+ * REMARKS:
+ * This funciton maps to the win32 GlobalFindAtom
+ */
+NTSTATUS
+STDCALL
+NtFindAtom(
+ IN PWSTR AtomName,
+ OUT PRTL_ATOM Atom OPTIONAL
+ );
+
+NTSTATUS
+STDCALL
+ZwFindAtom(
+ IN PWSTR AtomName,
+ OUT PRTL_ATOM Atom OPTIONAL
+ );
+
+/*
+ * FUNCTION: Flushes a the processors instruction cache
+ * ARGUMENTS:
+ * ProcessHandle = Points to the process owning the cache
+ * BaseAddress = // might this be a image address ????
+ * NumberOfBytesToFlush =
+ * RETURNS: Status
+ * REMARKS:
+ * This funciton is used by debuggers
+ */
+NTSTATUS
+STDCALL
+NtFlushInstructionCache(
+ IN HANDLE ProcessHandle,
+ IN PVOID BaseAddress,
+ IN UINT NumberOfBytesToFlush
+ );
+
+NTSTATUS
+STDCALL
+ZwFlushInstructionCache(
+ IN HANDLE ProcessHandle,
+ IN PVOID BaseAddress,
+ IN UINT NumberOfBytesToFlush
+ );
+
+/*
+ * FUNCTION: Flushes virtual memory to file
+ * ARGUMENTS:
+ * ProcessHandle = Points to the process that allocated the virtual memory
+ * BaseAddress = Points to the memory address
+ * NumberOfBytesToFlush = Limits the range to flush,
+ * NumberOfBytesFlushed = Actual number of bytes flushed
+ * RETURNS: Status
+ * REMARKS:
+ * Check return status on STATUS_NOT_MAPPED_DATA
+ */
+NTSTATUS
+STDCALL
+NtFlushVirtualMemory(
+ IN HANDLE ProcessHandle,
+ IN PVOID BaseAddress,
+ IN ULONG NumberOfBytesToFlush,
+ OUT PULONG NumberOfBytesFlushed OPTIONAL
+ );
+
+NTSTATUS
+STDCALL
+ZwFlushVirtualMemory(
+ IN HANDLE ProcessHandle,
+ IN PVOID BaseAddress,
+ IN ULONG NumberOfBytesToFlush,
+ OUT PULONG NumberOfBytesFlushed OPTIONAL
+ );
+
+/*
+ * FUNCTION: Retrieves the uptime of the system
+ * ARGUMENTS:
+ * UpTime = Number of clock ticks since boot.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtGetTickCount(
+ PULONG UpTime
+ );
+
+NTSTATUS
+STDCALL
+ZwGetTickCount(
+ PULONG UpTime
+ );
+
+/*
+ * FUNCTION: Loads a registry key.
+ * ARGUMENTS:
+ * KeyHandle = Handle to the registry key
+ * ObjectAttributes = ???
+ * REMARK:
+ * This procedure maps to the win32 procedure RegLoadKey
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtLoadKey(
+ PHANDLE KeyHandle,
+ POBJECT_ATTRIBUTES ObjectAttributes
+ );
+
+NTSTATUS
+STDCALL
+ZwLoadKey(
+ PHANDLE KeyHandle,
+ POBJECT_ATTRIBUTES ObjectAttributes
+ );
+
+/*
+ * FUNCTION: Locks a range of virtual memory.
+ * ARGUMENTS:
+ * ProcessHandle = Handle to the process
+ * BaseAddress = Lower boundary of the range of bytes to lock.
+ * NumberOfBytesLock = Offset to the upper boundary.
+ * NumberOfBytesLocked (OUT) = Number of bytes actually locked.
+ * REMARK:
+ This procedure maps to the win32 procedure VirtualLock
+ * RETURNS: Status [STATUS_SUCCESS | STATUS_WAS_LOCKED ]
+ */
+NTSTATUS
+STDCALL
+NtLockVirtualMemory(
+ HANDLE ProcessHandle,
+ PVOID BaseAddress,
+ ULONG NumberOfBytesToLock,
+ PULONG NumberOfBytesLocked
+ );
+
+NTSTATUS
+STDCALL
+ZwLockVirtualMemory(
+ HANDLE ProcessHandle,
+ PVOID BaseAddress,
+ ULONG NumberOfBytesToLock,
+ PULONG NumberOfBytesLocked
+ );
+
+NTSTATUS
+STDCALL
+NtOpenObjectAuditAlarm(
+ IN PUNICODE_STRING SubsystemName,
+ IN PVOID HandleId,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN HANDLE ClientToken,
+ IN ULONG DesiredAccess,
+ IN ULONG GrantedAccess,
+ IN PPRIVILEGE_SET Privileges,
+ IN BOOLEAN ObjectCreation,
+ IN BOOLEAN AccessGranted,
+ OUT PBOOLEAN GenerateOnClose
+ );
+
+NTSTATUS
+STDCALL
+ZwOpenObjectAuditAlarm(
+ IN PUNICODE_STRING SubsystemName,
+ IN PVOID HandleId,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN HANDLE ClientToken,
+ IN ULONG DesiredAccess,
+ IN ULONG GrantedAccess,
+ IN PPRIVILEGE_SET Privileges,
+ IN BOOLEAN ObjectCreation,
+ IN BOOLEAN AccessGranted,
+ OUT PBOOLEAN GenerateOnClose
+ );
+
+/*
+ * FUNCTION: Set the access protection of a range of virtual memory
+ * ARGUMENTS:
+ * ProcessHandle = Handle to process owning the virtual address space
+ * BaseAddress = Start address
+ * NumberOfBytesToProtect = Delimits the range of virtual memory
+ * for which the new access protection holds
+ * NewAccessProtection = The new access proctection for the pages
+ * OldAccessProtection = Caller should supply storage for the old
+ * access protection
+ *
+ * REMARKS:
+ * The function maps to the win32 VirtualProtectEx
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtProtectVirtualMemory(
+ IN HANDLE ProcessHandle,
+ IN PVOID BaseAddress,
+ IN ULONG NumberOfBytesToProtect,
+ IN ULONG NewAccessProtection,
+ OUT PULONG OldAccessProtection
+ );
+
+NTSTATUS
+STDCALL
+ZwProtectVirtualMemory(
+ IN HANDLE ProcessHandle,
+ IN PVOID BaseAddress,
+ IN ULONG NumberOfBytesToProtect,
+ IN ULONG NewAccessProtection,
+ OUT PULONG OldAccessProtection
+ );
+
+NTSTATUS
+STDCALL
+NtQueryInformationAtom(
+ IN RTL_ATOM Atom,
+ IN ATOM_INFORMATION_CLASS AtomInformationClass,
+ OUT PVOID AtomInformation,
+ IN ULONG AtomInformationLength,
+ OUT PULONG ReturnLength OPTIONAL
+ );
+
+NTSTATUS
+STDCALL
+ZwQueryInformationAtom(
+ IN RTL_ATOM Atom,
+ IN ATOM_INFORMATION_CLASS AtomInformationClass,
+ OUT PVOID AtomInformation,
+ IN ULONG AtomInformationLength,
+ OUT PULONG ReturnLength OPTIONAL
+ );
+
+/*
+ * FUNCTION: Query information about the content of a directory object
+ * ARGUMENTS:
+ DirObjInformation = Buffer must be large enough to hold the name strings too
+ GetNextIndex = If TRUE :return the index of the next object in this directory in ObjectIndex
+ If FALSE: return the number of objects in this directory in ObjectIndex
+ IgnoreInputIndex= If TRUE: ignore input value of ObjectIndex always start at index 0
+ If FALSE use input value of ObjectIndex
+ ObjectIndex = zero based index of object in the directory depends on GetNextIndex and IgnoreInputIndex
+ DataWritten = Actual size of the ObjectIndex ???
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtQueryDirectoryObject(
+ IN HANDLE DirObjHandle,
+ OUT POBJDIR_INFORMATION DirObjInformation,
+ IN ULONG BufferLength,
+ IN BOOLEAN GetNextIndex,
+ IN BOOLEAN IgnoreInputIndex,
+ IN OUT PULONG ObjectIndex,
+ OUT PULONG DataWritten OPTIONAL
+ );
+
+NTSTATUS
+STDCALL
+ZwQueryDirectoryObject(
+ IN HANDLE DirObjHandle,
+ OUT POBJDIR_INFORMATION DirObjInformation,
+ IN ULONG BufferLength,
+ IN BOOLEAN GetNextIndex,
+ IN BOOLEAN IgnoreInputIndex,
+ IN OUT PULONG ObjectIndex,
+ OUT PULONG DataWritten OPTIONAL
+ );
+
+/*
+ * FUNCTION: Queries the information of a process object.
+ * ARGUMENTS:
+ * ProcessHandle = Handle to the process object
+ * ProcessInformation = Index to a certain information structure
+
+ ProcessBasicInformation PROCESS_BASIC_INFORMATION
+ ProcessQuotaLimits QUOTA_LIMITS
+ ProcessIoCounters IO_COUNTERS
+ ProcessVmCounters VM_COUNTERS
+ ProcessTimes KERNEL_USER_TIMES
+ ProcessBasePriority KPRIORITY
+ ProcessRaisePriority KPRIORITY
+ ProcessDebugPort HANDLE
+ ProcessExceptionPort HANDLE
+ ProcessAccessToken PROCESS_ACCESS_TOKEN
+ ProcessLdtInformation LDT_ENTRY ??
+ ProcessLdtSize ULONG
+ ProcessDefaultHardErrorMode ULONG
+ ProcessIoPortHandlers // kernel mode only
+ ProcessPooledUsageAndLimits POOLED_USAGE_AND_LIMITS
+ ProcessWorkingSetWatch PROCESS_WS_WATCH_INFORMATION
+ ProcessUserModeIOPL (I/O Privilege Level)
+ ProcessEnableAlignmentFaultFixup BOOLEAN
+ ProcessPriorityClass ULONG
+ ProcessWx86Information ULONG
+ ProcessHandleCount ULONG
+ ProcessAffinityMask ULONG
+ ProcessPooledQuotaLimits QUOTA_LIMITS
+ MaxProcessInfoClass
+
+ * ProcessInformation = Caller supplies storage for the process information structure
+ * ProcessInformationLength = Size of the process information structure
+ * ReturnLength = Actual number of bytes written
+
+ * REMARK:
+ * This procedure maps to the win32 GetProcessTimes, GetProcessVersion,
+ GetProcessWorkingSetSize, GetProcessPriorityBoost, GetProcessAffinityMask, GetPriorityClass,
+ GetProcessShutdownParameters functions.
+ * RETURNS: Status
+*/
+
+NTSTATUS
+STDCALL
+NtQueryInformationProcess(
+ IN HANDLE ProcessHandle,
+ IN CINT ProcessInformationClass,
+ OUT PVOID ProcessInformation,
+ IN ULONG ProcessInformationLength,
+ OUT PULONG ReturnLength
+ );
+
+NTSTATUS
+STDCALL
+ZwQueryInformationProcess(
+ IN HANDLE ProcessHandle,
+ IN CINT ProcessInformationClass,
+ OUT PVOID ProcessInformation,
+ IN ULONG ProcessInformationLength,
+ OUT PULONG ReturnLength
+ );
+
+/*
+ * FUNCTION: Query the interval and the clocksource for profiling
+ * ARGUMENTS:
+ Interval =
+ ClockSource =
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtQueryIntervalProfile(
+ OUT PULONG Interval,
+ OUT KPROFILE_SOURCE ClockSource
+ );
+
+NTSTATUS
+STDCALL
+ZwQueryIntervalProfile(
+ OUT PULONG Interval,
+ OUT KPROFILE_SOURCE ClockSource
+ );
+
+/*
+ * FUNCTION: Queries the information of a object.
+ * ARGUMENTS:
+ ObjectHandle = Handle to a object
+ ObjectInformationClass = Index to a certain information structure
+
+ ObjectBasicInformation
+ ObjectTypeInformation OBJECT_TYPE_INFORMATION
+ ObjectNameInformation OBJECT_NAME_INFORMATION
+ ObjectDataInformation OBJECT_DATA_INFORMATION
+
+ ObjectInformation = Caller supplies storage for resulting information
+ Length = Size of the supplied storage
+ ResultLength = Bytes written
+ */
+
+NTSTATUS
+STDCALL
+NtQueryObject(
+ IN HANDLE ObjectHandle,
+ IN CINT ObjectInformationClass,
+ OUT PVOID ObjectInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+
+NTSTATUS
+STDCALL
+ZwQueryObject(
+ IN HANDLE ObjectHandle,
+ IN CINT ObjectInformationClass,
+ OUT PVOID ObjectInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+
+NTSTATUS
+STDCALL
+NtQuerySecurityObject(
+ IN HANDLE Object,
+ IN CINT SecurityObjectInformationClass,
+ OUT PVOID SecurityObjectInformation,
+ IN ULONG Length,
+ OUT PULONG ReturnLength
+ );
+
+NTSTATUS
+STDCALL
+ZwQuerySecurityObject(
+ IN HANDLE Object,
+ IN CINT SecurityObjectInformationClass,
+ OUT PVOID SecurityObjectInformation,
+ IN ULONG Length,
+ OUT PULONG ReturnLength
+ );
+
+/*
+ * FUNCTION: Queries the virtual memory information.
+ * ARGUMENTS:
+ ProcessHandle = Process owning the virtual address space
+ BaseAddress = Points to the page where the information is queried for.
+ * VirtualMemoryInformationClass = Index to a certain information structure
+
+ MemoryBasicInformation MEMORY_BASIC_INFORMATION
+
+ * VirtualMemoryInformation = caller supplies storage for the information structure
+ * Length = size of the structure
+ ResultLength = Data written
+ * RETURNS: Status
+ *
+*/
+
+NTSTATUS
+STDCALL
+NtQueryVirtualMemory(
+ IN HANDLE ProcessHandle,
+ IN PVOID Address,
+ IN IN CINT VirtualMemoryInformationClass,
+ OUT PVOID VirtualMemoryInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+
+NTSTATUS
+STDCALL
+ZwQueryVirtualMemory(
+ IN HANDLE ProcessHandle,
+ IN PVOID Address,
+ IN IN CINT VirtualMemoryInformationClass,
+ OUT PVOID VirtualMemoryInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+
+/*
+ * FUNCTION: Raises a hard error (stops the system)
+ * ARGUMENTS:
+ * Status = Status code of the hard error
+ * Unknown2 = ??
+ * Unknown3 = ??
+ * Unknown4 = ??
+ * Unknown5 = ??
+ * Unknown6 = ??
+ * RETURNS: Status
+ *
+ */
+
+NTSTATUS
+STDCALL
+NtRaiseHardError(
+ IN NTSTATUS Status,
+ ULONG Unknown2,
+ ULONG Unknown3,
+ ULONG Unknown4,
+ ULONG Unknown5,
+ ULONG Unknown6
+ );
+
+NTSTATUS
+STDCALL
+ZwRaiseHardError(
+ IN NTSTATUS Status,
+ ULONG Unknown2,
+ ULONG Unknown3,
+ ULONG Unknown4,
+ ULONG Unknown5,
+ ULONG Unknown6
+ );
+
+/*
+ * FUNCTION: Sets the information of a registry key.
+ * ARGUMENTS:
+ * KeyHandle = Handle to the registry key
+ * KeyInformationClass = Index to the a certain information structure.
+ Can be one of the following values:
+
+ * KeyWriteTimeInformation KEY_WRITE_TIME_INFORMATION
+
+ KeyInformation = Storage for the new information
+ * KeyInformationLength = Size of the information strucure
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtSetInformationKey(
+ IN HANDLE KeyHandle,
+ IN CINT KeyInformationClass,
+ IN PVOID KeyInformation,
+ IN ULONG KeyInformationLength
+ );
+
+NTSTATUS
+STDCALL
+ZwSetInformationKey(
+ IN HANDLE KeyHandle,
+ IN CINT KeyInformationClass,
+ IN PVOID KeyInformation,
+ IN ULONG KeyInformationLength
+ );
+
+/*
+ * FUNCTION: Changes a set of object specific parameters
+ * ARGUMENTS:
+ * ObjectHandle =
+ * ObjectInformationClass = Index to the set of parameters to change.
+
+
+ ObjectBasicInformation
+ ObjectTypeInformation OBJECT_TYPE_INFORMATION
+ ObjectAllInformation
+ ObjectDataInformation OBJECT_DATA_INFORMATION
+ ObjectNameInformation OBJECT_NAME_INFORMATION
+
+
+ * ObjectInformation = Caller supplies storage for parameters to set.
+ * Length = Size of the storage supplied
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetInformationObject(
+ IN HANDLE ObjectHandle,
+ IN CINT ObjectInformationClass,
+ IN PVOID ObjectInformation,
+ IN ULONG Length
+ );
+
+NTSTATUS
+STDCALL
+ZwSetInformationObject(
+ IN HANDLE ObjectHandle,
+ IN CINT ObjectInformationClass,
+ IN PVOID ObjectInformation,
+ IN ULONG Length
+ );
+
+/*
+ * FUNCTION: Changes a set of process specific parameters
+ * ARGUMENTS:
+ * ProcessHandle = Handle to the process
+ * ProcessInformationClass = Index to a information structure.
+ *
+ * ProcessBasicInformation PROCESS_BASIC_INFORMATION
+ * ProcessQuotaLimits QUOTA_LIMITS
+ * ProcessBasePriority KPRIORITY
+ * ProcessRaisePriority KPRIORITY
+ * ProcessDebugPort HANDLE
+ * ProcessExceptionPort HANDLE
+ * ProcessAccessToken PROCESS_ACCESS_TOKEN
+ * ProcessDefaultHardErrorMode ULONG
+ * ProcessPriorityClass ULONG
+ * ProcessAffinityMask KAFFINITY //??
+ *
+ * ProcessInformation = Caller supplies storage for information to set.
+ * ProcessInformationLength = Size of the information structure
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetInformationProcess(
+ IN HANDLE ProcessHandle,
+ IN CINT ProcessInformationClass,
+ IN PVOID ProcessInformation,
+ IN ULONG ProcessInformationLength
+ );
+
+NTSTATUS
+STDCALL
+ZwSetInformationProcess(
+ IN HANDLE ProcessHandle,
+ IN CINT ProcessInformationClass,
+ IN PVOID ProcessInformation,
+ IN ULONG ProcessInformationLength
+ );
+
+/*
+ * FUNCTION: Sets the characteristics of a timer
+ * ARGUMENTS:
+ * TimerHandle = Handle to the timer
+ * DueTime = Time before the timer becomes signalled for the first time.
+ * TimerApcRoutine = Completion routine can be called on time completion
+ * TimerContext = Argument to the completion routine
+ * Resume = Specifies if the timer should repeated after completing one cycle
+ * Period = Cycle of the timer
+ * REMARKS: This routine maps to the win32 SetWaitableTimer.
+ * RETURNS: Status
+*/
+NTSTATUS
+STDCALL
+NtSetTimer(
+ IN HANDLE TimerHandle,
+ IN PLARGE_INTEGER DueTime,
+ IN PTIMERAPCROUTINE TimerApcRoutine,
+ IN PVOID TimerContext,
+ IN BOOL WakeTimer,
+ IN ULONG Period OPTIONAL,
+ OUT PBOOLEAN PreviousState OPTIONAL
+ );
+
+NTSTATUS
+STDCALL
+ZwSetTimer(
+ IN HANDLE TimerHandle,
+ IN PLARGE_INTEGER DueTime,
+ IN PTIMERAPCROUTINE TimerApcRoutine,
+ IN PVOID TimerContext,
+ IN BOOL WakeTimer,
+ IN ULONG Period OPTIONAL,
+ OUT PBOOLEAN PreviousState OPTIONAL
+ );
+
+/*
+ * FUNCTION: Unloads a registry key.
+ * ARGUMENTS:
+ * KeyHandle = Handle to the registry key
+ * REMARK:
+ * This procedure maps to the win32 procedure RegUnloadKey
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtUnloadKey(
+ HANDLE KeyHandle
+ );
+
+NTSTATUS
+STDCALL
+ZwUnloadKey(
+ HANDLE KeyHandle
+ );
+
+/*
+ * FUNCTION: Unlocks a range of virtual memory.
+ * ARGUMENTS:
+ * ProcessHandle = Handle to the process
+ * BaseAddress = Lower boundary of the range of bytes to unlock.
+ * NumberOfBytesToUnlock = Offset to the upper boundary to unlock.
+ * NumberOfBytesUnlocked (OUT) = Number of bytes actually unlocked.
+ * REMARK:
+ This procedure maps to the win32 procedure VirtualUnlock
+ * RETURNS: Status [ STATUS_SUCCESS | STATUS_PAGE_WAS_ULOCKED ]
+ */
+NTSTATUS
+STDCALL
+NtUnlockVirtualMemory(
+ IN HANDLE ProcessHandle,
+ IN PVOID BaseAddress,
+ IN ULONG NumberOfBytesToUnlock,
+ OUT PULONG NumberOfBytesUnlocked OPTIONAL
+ );
+
+NTSTATUS
+STDCALL
+ZwUnlockVirtualMemory(
+ IN HANDLE ProcessHandle,
+ IN PVOID BaseAddress,
+ IN ULONG NumberOfBytesToUnlock,
+ OUT PULONG NumberOfBytesUnlocked OPTIONAL
+ );
+
+/*
+ * FUNCTION: Waits for multiple objects to become signalled.
+ * ARGUMENTS:
+ * Count = The number of objects
+ * Object = The array of object handles
+ * WaitType = Can be one of the values UserMode or KernelMode
+ * Alertable = If true the wait is alertable.
+ * Time = The maximum wait time.
+ * REMARKS:
+ * This function maps to the win32 WaitForMultipleObjectEx.
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtWaitForMultipleObjects (
+ IN ULONG Count,
+ IN HANDLE Object[],
+ IN CINT WaitType,
+ IN BOOLEAN Alertable,
+ IN PLARGE_INTEGER Time
+ );
+
+NTSTATUS
+STDCALL
+ZwWaitForMultipleObjects (
+ IN ULONG Count,
+ IN HANDLE Object[],
+ IN CINT WaitType,
+ IN BOOLEAN Alertable,
+ IN PLARGE_INTEGER Time
+ );
+
+/*
+ * FUNCTION: Creates a profile
+ * ARGUMENTS:
+ * ProfileHandle (OUT) = Caller supplied storage for the resulting handle
+ * ObjectAttribute = Initialized attributes for the object
+ * ImageBase = Start address of executable image
+ * ImageSize = Size of the image
+ * Granularity = Bucket size
+ * Buffer = Caller supplies buffer for profiling info
+ * ProfilingSize = Buffer size
+ * ClockSource = Specify 0 / FALSE ??
+ * ProcessorMask = A value of -1 indicates disables per processor profiling,
+ otherwise bit set for the processor to profile.
+ * REMARKS:
+ * This function maps to the win32 CreateProcess.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtCreateProfile(OUT PHANDLE ProfileHandle,
+ IN HANDLE ProcessHandle,
+ IN PVOID ImageBase,
+ IN ULONG ImageSize,
+ IN ULONG Granularity,
+ OUT PULONG Buffer,
+ IN ULONG ProfilingSize,
+ IN KPROFILE_SOURCE Source,
+ IN ULONG ProcessorMask);
+
+NTSTATUS
+STDCALL
+ZwCreateProfile(
+ OUT PHANDLE ProfileHandle,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN ULONG ImageBase,
+ IN ULONG ImageSize,
+ IN ULONG Granularity,
+ OUT PVOID Buffer,
+ IN ULONG ProfilingSize,
+ IN ULONG ClockSource,
+ IN ULONG ProcessorMask
+ );
+
+/*
+ * FUNCTION: Delays the execution of the calling thread.
+ * ARGUMENTS:
+ * Alertable = If TRUE the thread is alertable during is wait period
+ * Interval = Specifies the interval to wait.
+ * RETURNS: Status
+ */
+
+NTSTATUS
+STDCALL
+NtDelayExecution(
+ IN ULONG Alertable,
+ IN TIME *Interval
+ );
+
+NTSTATUS
+STDCALL
+ZwDelayExecution(
+ IN BOOLEAN Alertable,
+ IN TIME *Interval
+ );
+
+/*
+ * FUNCTION: Extends a section
+ * ARGUMENTS:
+ * SectionHandle = Handle to the section
+ * NewMaximumSize = Adjusted size
+ * RETURNS: Status
+ */
+NTSTATUS
+STDCALL
+NtExtendSection(
+ IN HANDLE SectionHandle,
+ IN ULONG NewMaximumSize
+ );
+
+NTSTATUS
+STDCALL
+ZwExtendSection(
+ IN HANDLE SectionHandle,
+ IN ULONG NewMaximumSize
+ );
+
+/*
+ * FUNCTION: Queries the information of a section object.
+ * ARGUMENTS:
+ * SectionHandle = Handle to the section link object
+ * SectionInformationClass = Index to a certain information structure
+ * SectionInformation (OUT)= Caller supplies storage for resulting information
+ * Length = Size of the supplied storage
+ * ResultLength = Data written
+ * RETURNS: Status
+ *
+*/
+NTSTATUS
+STDCALL
+NtQuerySection(
+ IN HANDLE SectionHandle,
+ IN CINT SectionInformationClass,
+ OUT PVOID SectionInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+
+NTSTATUS
+STDCALL
+ZwQuerySection(
+ IN HANDLE SectionHandle,
+ IN CINT SectionInformationClass,
+ OUT PVOID SectionInformation,
+ IN ULONG Length,
+ OUT PULONG ResultLength
+ );
+
+typedef struct _SECTION_IMAGE_INFORMATION
+{
+ PVOID EntryPoint;
+ ULONG Unknown1;
+ ULONG StackReserve;
+ ULONG StackCommit;
+ ULONG Subsystem;
+ USHORT MinorSubsystemVersion;
+ USHORT MajorSubsystemVersion;
+ ULONG Unknown2;
+ ULONG Characteristics;
+ USHORT ImageNumber;
+ BOOLEAN Executable;
+ UCHAR Unknown3;
+ ULONG Unknown4[3];
+} SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION;
+
+#endif /* !__USE_W32API */
+
+#endif /* __DDK_ZW_H */
--- /dev/null
+#ifndef __INCLUDE_DDK_ZWTYPES_H
+#define __INCLUDE_DDK_ZWTYPES_H
+
+#ifndef __USE_W32API
+
+typedef enum _DEBUG_CONTROL_CODE
+{
+ DebugGetTraceInformation = 1,
+ DebugSetInternalBreakpoint,
+ DebugSetSpecialCalls,
+ DebugClearSpecialCalls,
+ DebugQuerySpecialCalls,
+ DebugDbgBreakPoint,
+ DebugDbgLoadSymbols
+} DEBUG_CONTROL_CODE;
+
+typedef enum _KPROFILE_SOURCE
+{
+ ProfileTime
+} KPROFILE_SOURCE;
+
+// file disposition values
+
+#define FILE_SUPERSEDE 0x0000
+#define FILE_OPEN 0x0001
+#define FILE_CREATE 0x0002
+#define FILE_OPEN_IF 0x0003
+#define FILE_OVERWRITE 0x0004
+#define FILE_OVERWRITE_IF 0x0005
+#define FILE_MAXIMUM_DISPOSITION 0x0005
+
+// job query / set information class
+
+typedef enum _JOBOBJECTINFOCLASS { // Q S
+ JobObjectBasicAccountingInformation = 1, // Y N
+ JobObjectBasicLimitInformation, // Y Y
+ JobObjectBasicProcessIdList, // Y N
+ JobObjectBasicUIRestrictions, // Y Y
+ JobObjectSecurityLimitInformation, // Y Y
+ JobObjectEndOfJobTimeInformation, // N Y
+ JobObjectAssociateCompletionPortInformation, // N Y
+ JobObjectBasicAndIoAccountingInformation, // Y N
+ JobObjectExtendedLimitInformation, // Y Y
+} JOBOBJECTINFOCLASS;
+
+// system information
+// {Nt|Zw}{Query|Set}SystemInformation
+// (GN means Gary Nebbet in "NT/W2K Native API Reference")
+
+typedef
+enum _SYSTEM_INFORMATION_CLASS
+{
+ SystemInformationClassMin = 0,
+ SystemBasicInformation = 0, /* Q */
+
+ SystemProcessorInformation = 1, /* Q */
+
+ SystemPerformanceInformation = 2, /* Q */
+
+ SystemTimeOfDayInformation = 3, /* Q */
+
+ SystemPathInformation = 4, /* Q (checked build only) */
+ SystemNotImplemented1 = 4, /* Q (GN) */
+
+ SystemProcessInformation = 5, /* Q */
+ SystemProcessesAndThreadsInformation = 5, /* Q (GN) */
+
+ SystemCallCountInfoInformation = 6, /* Q */
+ SystemCallCounts = 6, /* Q (GN) */
+
+ SystemDeviceInformation = 7, /* Q */
+// It conflicts with symbol in ntoskrnl/io/resource.c
+// SystemConfigurationInformation = 7, /* Q (GN) */
+
+ SystemProcessorPerformanceInformation = 8, /* Q */
+ SystemProcessorTimes = 8, /* Q (GN) */
+
+ SystemFlagsInformation = 9, /* QS */
+ SystemGlobalFlag = 9, /* QS (GN) */
+
+ SystemCallTimeInformation = 10,
+ SystemNotImplemented2 = 10, /* (GN) */
+
+ SystemModuleInformation = 11, /* Q */
+
+ SystemLocksInformation = 12, /* Q */
+ SystemLockInformation = 12, /* Q (GN) */
+
+ SystemStackTraceInformation = 13,
+ SystemNotImplemented3 = 13, /* Q (GN) */
+
+ SystemPagedPoolInformation = 14,
+ SystemNotImplemented4 = 14, /* Q (GN) */
+
+ SystemNonPagedPoolInformation = 15,
+ SystemNotImplemented5 = 15, /* Q (GN) */
+
+ SystemHandleInformation = 16, /* Q */
+
+ SystemObjectInformation = 17, /* Q */
+
+ SystemPageFileInformation = 18, /* Q */
+ SystemPagefileInformation = 18, /* Q (GN) */
+
+ SystemVdmInstemulInformation = 19, /* Q */
+ SystemInstructionEmulationCounts = 19, /* Q (GN) */
+
+ SystemVdmBopInformation = 20,
+ SystemInvalidInfoClass1 = 20, /* (GN) */
+
+ SystemFileCacheInformation = 21, /* QS */
+ SystemCacheInformation = 21, /* QS (GN) */
+
+ SystemPoolTagInformation = 22, /* Q (checked build only) */
+
+ SystemInterruptInformation = 23, /* Q */
+ SystemProcessorStatistics = 23, /* Q (GN) */
+
+ SystemDpcBehaviourInformation = 24, /* QS */
+ SystemDpcInformation = 24, /* QS (GN) */
+
+ SystemFullMemoryInformation = 25,
+ SystemNotImplemented6 = 25, /* (GN) */
+
+ SystemLoadImage = 26, /* S (callable) (GN) */
+
+ SystemUnloadImage = 27, /* S (callable) (GN) */
+
+ SystemTimeAdjustmentInformation = 28, /* QS */
+ SystemTimeAdjustment = 28, /* QS (GN) */
+
+ SystemSummaryMemoryInformation = 29,
+ SystemNotImplemented7 = 29, /* (GN) */
+
+ SystemNextEventIdInformation = 30,
+ SystemNotImplemented8 = 30, /* (GN) */
+
+ SystemEventIdsInformation = 31,
+ SystemNotImplemented9 = 31, /* (GN) */
+
+ SystemCrashDumpInformation = 32, /* Q */
+
+ SystemExceptionInformation = 33, /* Q */
+
+ SystemCrashDumpStateInformation = 34, /* Q */
+
+ SystemKernelDebuggerInformation = 35, /* Q */
+
+ SystemContextSwitchInformation = 36, /* Q */
+
+ SystemRegistryQuotaInformation = 37, /* QS */
+
+ SystemLoadAndCallImage = 38, /* S (GN) */
+
+ SystemPrioritySeparation = 39, /* S */
+
+ SystemPlugPlayBusInformation = 40,
+ SystemNotImplemented10 = 40, /* Q (GN) */
+
+ SystemDockInformation = 41,
+ SystemNotImplemented11 = 41, /* Q (GN) */
+
+ SystemPowerInformation = 42,
+ SystemInvalidInfoClass2 = 42, /* (GN) */
+
+ SystemProcessorSpeedInformation = 43,
+ SystemInvalidInfoClass3 = 43, /* (GN) */
+
+ SystemCurrentTimeZoneInformation = 44, /* QS */
+ SystemTimeZoneInformation = 44, /* QS (GN) */
+
+ SystemLookasideInformation = 45, /* Q */
+
+ SystemSetTimeSlipEvent = 46, /* S (GN) */
+
+ SystemCreateSession = 47, /* S (GN) */
+
+ SystemDeleteSession = 48, /* S (GN) */
+
+ SystemInvalidInfoClass4 = 49, /* (GN) */
+
+ SystemRangeStartInformation = 50, /* Q (GN) */
+
+ SystemVerifierInformation = 51, /* QS (GN) */
+
+ SystemAddVerifier = 52, /* S (GN) */
+
+ SystemSessionProcessesInformation = 53, /* Q (GN) */
+ SystemInformationClassMax
+
+} SYSTEM_INFORMATION_CLASS;
+
+// SystemBasicInformation (0)
+typedef
+struct _SYSTEM_BASIC_INFORMATION
+{
+ ULONG Reserved;
+ ULONG TimerResolution;
+ ULONG PageSize;
+ ULONG NumberOfPhysicalPages;
+ ULONG LowestPhysicalPageNumber;
+ ULONG HighestPhysicalPageNumber;
+ ULONG AllocationGranularity;
+ ULONG MinimumUserModeAddress;
+ ULONG MaximumUserModeAddress;
+ KAFFINITY ActiveProcessorsAffinityMask;
+ CCHAR NumberOfProcessors;
+} SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION;
+
+// SystemProcessorInformation (1)
+typedef
+struct _SYSTEM_PROCESSOR_INFORMATION
+{
+ USHORT ProcessorArchitecture;
+ USHORT ProcessorLevel;
+ USHORT ProcessorRevision;
+ USHORT Reserved;
+ ULONG ProcessorFeatureBits;
+} SYSTEM_PROCESSOR_INFORMATION, *PSYSTEM_PROCESSOR_INFORMATION;
+
+// SystemPerformanceInfo (2)
+typedef
+struct _SYSTEM_PERFORMANCE_INFORMATION
+{
+ LARGE_INTEGER IdleProcessorTime;
+ LARGE_INTEGER IoReadTransferCount;
+ LARGE_INTEGER IoWriteTransferCount;
+ LARGE_INTEGER IoOtherTransferCount;
+ ULONG IoReadOperationCount;
+ ULONG IoWriteOperationCount;
+ ULONG IoOtherOperationCount;
+ ULONG AvailablePages;
+ ULONG CommitedPages;
+ ULONG CommitLimit;
+ ULONG PeakCommitment;
+ ULONG PageFaultCount;
+ ULONG CopyOnWriteCount;
+ ULONG TransitionCount;
+ ULONG CacheTransitionCount;
+ ULONG DemandZeroCount;
+ ULONG PageReadCount;
+ ULONG PageReadIoCount;
+ ULONG CacheReadCount;
+ ULONG CacheIoCount;
+ ULONG DirtyPagesWriteCount;
+ ULONG DirtyWriteIoCount;
+ ULONG MappedPagesWriteCount;
+ ULONG MappedWriteIoCount;
+ ULONG PagedPoolPages;
+ ULONG NonPagedPoolPages;
+ ULONG Unknown6;
+ ULONG Unknown7;
+ ULONG Unknown8;
+ ULONG Unknown9;
+ ULONG MmTotalSystemFreePtes;
+ ULONG MmSystemCodepage;
+ ULONG MmTotalSystemDriverPages;
+ ULONG MmTotalSystemCodePages;
+ ULONG Unknown10;
+ ULONG Unknown11;
+ ULONG Unknown12;
+ ULONG MmSystemCachePage;
+ ULONG MmPagedPoolPage;
+ ULONG MmSystemDriverPage;
+ ULONG CcFastReadNoWait;
+ ULONG CcFastReadWait;
+ ULONG CcFastReadResourceMiss;
+ ULONG CcFastReadNotPossible;
+ ULONG CcFastMdlReadNoWait;
+ ULONG CcFastMdlReadWait;
+ ULONG CcFastMdlReadResourceMiss;
+ ULONG CcFastMdlReadNotPossible;
+ ULONG CcMapDataNoWait;
+ ULONG CcMapDataWait;
+ ULONG CcMapDataNoWaitMiss;
+ ULONG CcMapDataWaitMiss;
+ ULONG CcPinMappedDataCount;
+ ULONG CcPinReadNoWait;
+ ULONG CcPinReadWait;
+ ULONG CcPinReadNoWaitMiss;
+ ULONG CcPinReadWaitMiss;
+ ULONG CcCopyReadNoWait;
+ ULONG CcCopyReadWait;
+ ULONG CcCopyReadNoWaitMiss;
+ ULONG CcCopyReadWaitMiss;
+ ULONG CcMdlReadNoWait;
+ ULONG CcMdlReadWait;
+ ULONG CcMdlReadNoWaitMiss;
+ ULONG CcMdlReadWaitMiss;
+ ULONG CcReadaheadIos;
+ ULONG CcLazyWriteIos;
+ ULONG CcLazyWritePages;
+ ULONG CcDataFlushes;
+ ULONG CcDataPages;
+ ULONG ContextSwitches;
+ ULONG Unknown13;
+ ULONG Unknown14;
+ ULONG SystemCalls;
+
+} SYSTEM_PERFORMANCE_INFO, *PSYSTEM_PERFORMANCE_INFO;
+
+// SystemModuleInformation (11)
+typedef
+struct _SYSTEM_MODULE_ENTRY
+{
+ ULONG Unknown1;
+ ULONG Unknown2;
+ PVOID BaseAddress;
+ ULONG Size;
+ ULONG Flags;
+ ULONG EntryIndex;
+ USHORT NameLength; /* Length of module name not including the path, this field contains valid value only for NTOSKRNL module*/
+ USHORT PathLength; /* Length of 'directory path' part of modulename*/
+ CHAR Name [256];
+} SYSTEM_MODULE_ENTRY, * PSYSTEM_MODULE_ENTRY;
+
+typedef
+struct _SYSTEM_MODULE_INFORMATION
+{
+ ULONG Count;
+ SYSTEM_MODULE_ENTRY Module [1];
+} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
+
+// SystemHandleInformation (16)
+// (see ontypes.h)
+typedef
+struct _SYSTEM_HANDLE_ENTRY
+{
+ ULONG OwnerPid;
+ BYTE ObjectType;
+ BYTE HandleFlags;
+ USHORT HandleValue;
+ PVOID ObjectPointer;
+ ULONG AccessMask;
+
+} SYSTEM_HANDLE_ENTRY, *PSYSTEM_HANDLE_ENTRY;
+
+typedef
+struct _SYSTEM_HANDLE_INFORMATION
+{
+ ULONG Count;
+ SYSTEM_HANDLE_ENTRY Handle [1];
+
+} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
+
+// SystemObjectInformation (17)
+typedef
+struct _SYSTEM_OBJECT_TYPE_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG ObjectCount;
+ ULONG HandleCount;
+ ULONG TypeNumber;
+ ULONG InvalidAttributes;
+ GENERIC_MAPPING GenericMapping;
+ ACCESS_MASK ValidAccessMask;
+ POOL_TYPE PoolType;
+ UCHAR Unknown;
+ UNICODE_STRING Name;
+
+} SYSTEM_OBJECT_TYPE_INFORMATION, *PSYSTEM_OBJECT_TYPE_INFORMATION;
+
+typedef
+struct _SYSTEM_OBJECT_INFORMATION
+{
+ ULONG NextEntryOffset;
+ PVOID Object;
+ ULONG CreatorProcessId;
+ USHORT Unknown;
+ USHORT Flags;
+ ULONG PointerCount;
+ ULONG HandleCount;
+ ULONG PagedPoolUsage;
+ ULONG NonPagedPoolUsage;
+ ULONG ExclusiveProcessId;
+ PSECURITY_DESCRIPTOR SecurityDescriptor;
+ UNICODE_STRING Name;
+
+} SYSTEM_OBJECT_INFORMATION, *PSYSTEM_OBJECT_INFORMATION;
+
+// SystemPageFileInformation (18)
+typedef
+struct _SYSTEM_PAGEFILE_INFORMATION
+{
+ ULONG RelativeOffset;
+ ULONG CurrentSizePages;
+ ULONG TotalUsedPages;
+ ULONG PeakUsedPages;
+ UNICODE_STRING PagefileFileName;
+
+} SYSTEM_PAGEFILE_INFORMATION, *PSYSTEM_PAGEFILE_INFORMATION;
+
+// SystemCacheInformation (21)
+typedef
+struct _SYSTEM_CACHE_INFORMATION
+{
+ ULONG CurrentSize;
+ ULONG PeakSize;
+ ULONG PageFaultCount;
+ ULONG MinimumWorkingSet;
+ ULONG MaximumWorkingSet;
+ ULONG Unused[4];
+
+} SYSTEM_CACHE_INFORMATION;
+
+// SystemDpcInformation (24)
+typedef
+struct _SYSTEM_DPC_INFORMATION
+{
+ ULONG Unused;
+ ULONG KiMaximumDpcQueueDepth;
+ ULONG KiMinimumDpcRate;
+ ULONG KiAdjustDpcThreshold;
+ ULONG KiIdealDpcRate;
+
+} SYSTEM_DPC_INFORMATION, *PSYSTEM_DPC_INFORMATION;
+
+// SystemLoadImage (26)
+typedef struct _SYSTEM_LOAD_IMAGE
+{
+ UNICODE_STRING ModuleName;
+ PVOID ModuleBase;
+ PVOID SectionPointer;
+ PVOID EntryPoint;
+ PVOID ExportDirectory;
+} SYSTEM_LOAD_IMAGE, *PSYSTEM_LOAD_IMAGE;
+
+// SystemUnloadImage (27)
+typedef struct _SYSTEM_UNLOAD_IMAGE
+{
+ PVOID ModuleBase;
+} SYSTEM_UNLOAD_IMAGE, *PSYSTEM_UNLOAD_IMAGE;
+
+// SystemTimeAdjustmentInformation (28)
+typedef
+struct _SYSTEM_QUERY_TIME_ADJUSTMENT
+{
+ ULONG TimeAdjustment;
+ ULONG MaximumIncrement;
+ BOOLEAN TimeSynchronization;
+
+} SYSTEM_QUERY_TIME_ADJUSTMENT, *PSYSTEM_QUERY_TIME_ADJUSTMENT;
+
+typedef
+struct _SYSTEM_SET_TIME_ADJUSTMENT
+{
+ ULONG TimeAdjustment;
+ BOOLEAN TimeSynchronization;
+
+} SYSTEM_TIME_ADJUSTMENT_INFO, *PSYSTEM_TIME_ADJUSTMENT_INFO;
+
+// atom information
+
+typedef enum _ATOM_INFORMATION_CLASS
+{
+ AtomBasicInformation = 0,
+ AtomTableInformation = 1,
+} ATOM_INFORMATION_CLASS;
+
+typedef struct _ATOM_BASIC_INFORMATION
+{
+ USHORT UsageCount;
+ USHORT Flags;
+ USHORT NameLength;
+ WCHAR Name[1];
+} ATOM_BASIC_INFORMATION, *PATOM_BASIC_INFORMATION;
+
+// SystemLoadAndCallImage(38)
+typedef struct _SYSTEM_LOAD_AND_CALL_IMAGE
+{
+ UNICODE_STRING ModuleName;
+} SYSTEM_LOAD_AND_CALL_IMAGE, *PSYSTEM_LOAD_AND_CALL_IMAGE;
+
+// SystemTimeZoneInformation (44)
+typedef
+struct _SYSTEM_TIME_ZONE_INFORMATION
+{
+ LONG Bias;
+ WCHAR StandardName [32];
+ TIME StandardDate;
+ LONG StandardBias;
+ WCHAR DaylightName [32];
+ TIME DaylightDate;
+ LONG DaylightBias;
+
+} SYSTEM_TIME_ZONE_INFORMATION, * PSYSTEM_TIME_ZONE_INFORMATION;
+
+// SystemLookasideInformation (45)
+typedef
+struct _SYSTEM_LOOKASIDE_INFORMATION
+{
+ USHORT Depth;
+ USHORT MaximumDepth;
+ ULONG TotalAllocates;
+ ULONG AllocatesMisses;
+ ULONG TotalFrees;
+ ULONG FreeMisses;
+ POOL_TYPE Type;
+ ULONG Tag;
+ ULONG Size;
+
+} SYSTEM_LOOKASIDE_INFORMATION, * PSYSTEM_LOOKASIDE_INFORMATION;
+
+// SystemSetTimeSlipEvent (46)
+typedef
+struct _SYSTEM_SET_TIME_SLIP_EVENT
+{
+ HANDLE TimeSlipEvent; /* IN */
+
+} SYSTEM_SET_TIME_SLIP_EVENT, * PSYSTEM_SET_TIME_SLIP_EVENT;
+
+// SystemCreateSession (47)
+// (available only on TSE/NT5+)
+typedef
+struct _SYSTEM_CREATE_SESSION
+{
+ ULONG SessionId; /* OUT */
+
+} SYSTEM_CREATE_SESSION, * PSYSTEM_CREATE_SESSION;
+
+// SystemDeleteSession (48)
+// (available only on TSE/NT5+)
+typedef
+struct _SYSTEM_DELETE_SESSION
+{
+ ULONG SessionId; /* IN */
+
+} SYSTEM_DELETE_SESSION, * PSYSTEM_DELETE_SESSION;
+
+// SystemRangeStartInformation (50)
+typedef
+struct _SYSTEM_RANGE_START_INFORMATION
+{
+ PVOID SystemRangeStart;
+
+} SYSTEM_RANGE_START_INFORMATION, * PSYSTEM_RANGE_START_INFORMATION;
+
+// SystemSessionProcessesInformation (53)
+// (available only on TSE/NT5+)
+typedef
+struct _SYSTEM_SESSION_PROCESSES_INFORMATION
+{
+ ULONG SessionId;
+ ULONG BufferSize;
+ PVOID Buffer; /* same format as in SystemProcessInformation */
+
+} SYSTEM_SESSION_PROCESSES_INFORMATION, * PSYSTEM_SESSION_PROCESSES_INFORMATION;
+
+// memory information
+
+typedef enum _MEMORY_INFORMATION_CLASS {
+ MemoryBasicInformation,
+ MemoryWorkingSetList,
+ MemorySectionName //,
+ //MemoryBasicVlmInformation //???
+} MEMORY_INFORMATION_CLASS;
+
+typedef struct _MEMORY_BASIC_INFORMATION { // Information Class 0
+ PVOID BaseAddress;
+ PVOID AllocationBase;
+ ULONG AllocationProtect;
+ ULONG RegionSize;
+ ULONG State;
+ ULONG Protect;
+ ULONG Type;
+} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
+
+typedef struct _MEMORY_WORKING_SET_LIST { // Information Class 1
+ ULONG NumberOfPages;
+ ULONG WorkingSetList[1];
+} MEMORY_WORKING_SET_LIST, *PMEMORY_WORKING_SET_LIST;
+
+// Information Class 2
+#define _MEMORY_SECTION_NAME_STATIC(__bufsize__) \
+ { \
+ UNICODE_STRING SectionFileName; \
+ WCHAR NameBuffer[(__bufsize__)]; \
+}
+
+#define MEMORY_SECTION_NAME_STATIC(__bufsize__) \
+ struct _MEMORY_SECTION_NAME_STATIC((__bufsize__)
+
+typedef struct _MEMORY_SECTION_NAME_STATIC(ANYSIZE_ARRAY)
+ MEMORY_SECTION_NAME, *PMEMORY_SECTION_NAME;
+
+// Information class 0
+typedef struct _PROCESS_BASIC_INFORMATION
+{
+ NTSTATUS ExitStatus;
+ PPEB PebBaseAddress;
+ KAFFINITY AffinityMask;
+ KPRIORITY BasePriority;
+ ULONG UniqueProcessId;
+ ULONG InheritedFromUniqueProcessId;
+} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;
+
+// Information class 1
+typedef struct _QUOTA_LIMITS
+{
+ ULONG PagedPoolLimit;
+ ULONG NonPagedPoolLimit;
+ ULONG MinimumWorkingSetSize;
+ ULONG MaximumWorkingSetSize;
+ ULONG PagefileLimit;
+ TIME TimeLimit;
+} QUOTA_LIMITS, *PQUOTA_LIMITS;
+
+// Information class 2
+typedef struct _IO_COUNTERS
+{
+ ULONG ReadOperationCount;
+ ULONG WriteOperationCount;
+ ULONG OtherOperationCount;
+ LARGE_INTEGER ReadTransferCount;
+ LARGE_INTEGER WriteTransferCount;
+ LARGE_INTEGER OtherTransferCount;
+} IO_COUNTERS, *PIO_COUNTERS;
+
+// Information class 3
+typedef struct _VM_COUNTERS_
+{
+ ULONG PeakVirtualSize;
+ ULONG VirtualSize;
+ ULONG PageFaultCount;
+ ULONG PeakWorkingSetSize;
+ ULONG WorkingSetSize;
+ ULONG QuotaPeakPagedPoolUsage;
+ ULONG QuotaPagedPoolUsage;
+ ULONG QuotaPeakNonPagedPoolUsage;
+ ULONG QuotaNonPagedPoolUsage;
+ ULONG PagefileUsage;
+ ULONG PeakPagefileUsage;
+} VM_COUNTERS, *PVM_COUNTERS;
+
+// Information class 4
+typedef struct _KERNEL_USER_TIMES
+{
+ TIME CreateTime;
+ TIME ExitTime;
+ TIME KernelTime;
+ TIME UserTime;
+} KERNEL_USER_TIMES, *PKERNEL_USER_TIMES;
+
+// Information class 9
+typedef struct _PROCESS_ACCESS_TOKEN
+{
+ HANDLE Token;
+ HANDLE Thread;
+} PROCESS_ACCESS_TOKEN, *PPROCESS_ACCESS_TOKEN;
+
+// Information class 14
+typedef struct _POOLED_USAGE_AND_LIMITS_
+{
+ ULONG PeakPagedPoolUsage;
+ ULONG PagedPoolUsage;
+ ULONG PagedPoolLimit;
+ ULONG PeakNonPagedPoolUsage;
+ ULONG NonPagedPoolUsage;
+ ULONG NonPagedPoolLimit;
+ ULONG PeakPagefileUsage;
+ ULONG PagefileUsage;
+ ULONG PagefileLimit;
+} POOLED_USAGE_AND_LIMITS, *PPOOLED_USAGE_AND_LIMITS;
+
+// Information class 15
+typedef struct _PROCESS_WS_WATCH_INFORMATION
+{
+ PVOID FaultingPc;
+ PVOID FaultingVa;
+} PROCESS_WS_WATCH_INFORMATION, *PPROCESS_WS_WATCH_INFORMATION;
+
+// Information class 18
+typedef struct _PROCESS_PRIORITY_CLASS
+{
+ BOOLEAN Foreground;
+ UCHAR PriorityClass;
+} PROCESS_PRIORITY_CLASS, *PPROCESS_PRIORITY_CLASS;
+
+// Information class 23
+typedef struct _PROCESS_DEVICEMAP_INFORMATION
+{
+ union {
+ struct {
+ HANDLE DirectoryHandle;
+ } Set;
+ struct {
+ ULONG DriveMap;
+ UCHAR DriveType[32];
+ } Query;
+ };
+} PROCESS_DEVICEMAP_INFORMATION, *pPROCESS_DEVICEMAP_INFORMATION;
+
+// Information class 24
+typedef struct _PROCESS_SESSION_INFORMATION
+{
+ ULONG SessionId;
+} PROCESS_SESSION_INFORMATION, *PPROCESS_SESSION_INFORMATION;
+
+// thread information
+
+// incompatible with MS NT
+
+typedef struct _THREAD_BASIC_INFORMATION
+{
+ NTSTATUS ExitStatus;
+ PVOID TebBaseAddress; // PNT_TIB (GN)
+ CLIENT_ID ClientId;
+ KAFFINITY AffinityMask;
+ KPRIORITY Priority;
+ KPRIORITY BasePriority;
+} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;
+
+// object information
+
+typedef struct _OBJECT_NAME_INFORMATION
+{
+ UNICODE_STRING Name;
+} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
+
+// file information
+
+typedef struct _FILE_BASIC_INFORMATION
+{
+ TIME CreationTime;
+ TIME LastAccessTime;
+ TIME LastWriteTime;
+ TIME ChangeTime;
+ ULONG FileAttributes;
+} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
+
+typedef struct _FILE_STANDARD_INFORMATION
+{
+ LARGE_INTEGER AllocationSize;
+ LARGE_INTEGER EndOfFile;
+ ULONG NumberOfLinks;
+ BOOLEAN DeletePending;
+ BOOLEAN Directory;
+} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
+
+typedef struct _FILE_POSITION_INFORMATION
+{
+ LARGE_INTEGER CurrentByteOffset;
+} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;
+
+typedef struct _FILE_ALIGNMENT_INFORMATION
+{
+ ULONG AlignmentRequirement;
+} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION;
+
+typedef struct _FILE_DISPOSITION_INFORMATION
+{
+ BOOLEAN DoDeleteFile;
+} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION;
+
+typedef struct _FILE_END_OF_FILE_INFORMATION
+{
+ LARGE_INTEGER EndOfFile;
+} FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION;
+
+typedef struct _FILE_NETWORK_OPEN_INFORMATION
+{
+ TIME CreationTime;
+ TIME LastAccessTime;
+ TIME LastWriteTime;
+ TIME ChangeTime;
+ LARGE_INTEGER AllocationSize;
+ LARGE_INTEGER EndOfFile;
+ ULONG FileAttributes;
+} FILE_NETWORK_OPEN_INFORMATION, *PFILE_NETWORK_OPEN_INFORMATION;
+
+typedef struct _FILE_FULL_EA_INFORMATION
+{
+ ULONG NextEntryOffset;
+ UCHAR Flags;
+ UCHAR EaNameLength;
+ USHORT EaValueLength;
+ CHAR EaName[0];
+} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;
+
+
+typedef struct _FILE_EA_INFORMATION {
+ ULONG EaSize;
+} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION;
+
+
+typedef struct _FILE_GET_EA_INFORMATION {
+ ULONG NextEntryOffset;
+ UCHAR EaNameLength;
+ CHAR EaName[0];
+} FILE_GET_EA_INFORMATION, *PFILE_GET_EA_INFORMATION;
+
+typedef struct _FILE_STREAM_INFORMATION {
+ ULONG NextEntryOffset;
+ ULONG StreamNameLength;
+ LARGE_INTEGER StreamSize;
+ LARGE_INTEGER StreamAllocationSize;
+ WCHAR StreamName[0];
+} FILE_STREAM_INFORMATION, *PFILE_STREAM_INFORMATION;
+
+typedef struct _FILE_ALLOCATION_INFORMATION {
+ LARGE_INTEGER AllocationSize;
+} FILE_ALLOCATION_INFORMATION, *PFILE_ALLOCATION_INFORMATION;
+
+typedef struct _FILE_NAME_INFORMATION {
+ ULONG FileNameLength;
+ WCHAR FileName[0];
+} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
+
+typedef struct _FILE_NAMES_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ ULONG FileNameLength;
+ WCHAR FileName[0];
+} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;
+
+
+typedef struct _FILE_RENAME_INFORMATION {
+ BOOLEAN Replace;
+ HANDLE RootDir;
+ ULONG FileNameLength;
+ WCHAR FileName[0];
+} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION;
+
+
+typedef struct _FILE_INTERNAL_INFORMATION {
+ LARGE_INTEGER IndexNumber;
+} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION;
+
+typedef struct _FILE_ACCESS_INFORMATION {
+ ACCESS_MASK AccessFlags;
+} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION;
+
+
+typedef struct _FILE_MODE_INFORMATION {
+ ULONG Mode;
+} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION;
+
+
+typedef struct _FILE_PIPE_INFORMATION {
+ ULONG ReadMode;
+ ULONG CompletionMode;
+} FILE_PIPE_INFORMATION, *PFILE_PIPE_INFORMATION;
+
+typedef struct _FILE_PIPE_LOCAL_INFORMATION {
+ ULONG NamedPipeType;
+ ULONG NamedPipeConfiguration;
+ ULONG MaximumInstances;
+ ULONG CurrentInstances;
+ ULONG InboundQuota;
+ ULONG ReadDataAvailable;
+ ULONG OutboundQuota;
+ ULONG WriteQuotaAvailable;
+ ULONG NamedPipeState;
+ ULONG NamedPipeEnd;
+} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
+
+typedef struct _FILE_PIPE_REMOTE_INFORMATION {
+ LARGE_INTEGER CollectDataTime;
+ ULONG MaximumCollectionCount;
+} FILE_PIPE_REMOTE_INFORMATION, *PFILE_PIPE_REMOTE_INFORMATION;
+
+typedef struct _FILE_MAILSLOT_QUERY_INFORMATION {
+ ULONG MaxMessageSize;
+ ULONG Unknown; /* ?? */
+ ULONG NextSize;
+ ULONG MessageCount;
+ LARGE_INTEGER Timeout;
+} FILE_MAILSLOT_QUERY_INFORMATION, *PFILE_MAILSLOT_QUERY_INFORMATION;
+
+typedef struct _FILE_MAILSLOT_SET_INFORMATION {
+ LARGE_INTEGER Timeout;
+} FILE_MAILSLOT_SET_INFORMATION, *PFILE_MAILSLOT_SET_INFORMATION;
+
+typedef struct _FILE_COMPRESSION_INFORMATION {
+ LARGE_INTEGER CompressedFileSize;
+ USHORT CompressionFormat;
+ UCHAR CompressionUnitShift;
+ UCHAR ChunkShift;
+ UCHAR ClusterShift;
+ UCHAR Reserved[3];
+} FILE_COMPRESSION_INFORMATION, *PFILE_COMPRESSION_INFORMATION;
+
+typedef struct _FILE_ALL_INFORMATION {
+ FILE_BASIC_INFORMATION BasicInformation;
+ FILE_STANDARD_INFORMATION StandardInformation;
+ FILE_INTERNAL_INFORMATION InternalInformation;
+ FILE_EA_INFORMATION EaInformation;
+ FILE_ACCESS_INFORMATION AccessInformation;
+ FILE_POSITION_INFORMATION PositionInformation;
+ FILE_MODE_INFORMATION ModeInformation;
+ FILE_ALIGNMENT_INFORMATION AlignmentInformation;
+ FILE_NAME_INFORMATION NameInformation;
+} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION;
+
+
+// file system information structures
+
+typedef struct _FILE_FS_DEVICE_INFORMATION {
+ DEVICE_TYPE DeviceType;
+ ULONG Characteristics;
+} FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION;
+
+
+typedef struct _FILE_FS_VOLUME_INFORMATION {
+ TIME VolumeCreationTime;
+ ULONG VolumeSerialNumber;
+ ULONG VolumeLabelLength;
+ BOOLEAN SupportsObjects;
+ WCHAR VolumeLabel[0];
+} FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION;
+
+typedef struct _FILE_FS_SIZE_INFORMATION {
+ LARGE_INTEGER TotalAllocationUnits;
+ LARGE_INTEGER AvailableAllocationUnits;
+ ULONG SectorsPerAllocationUnit;
+ ULONG BytesPerSector;
+} FILE_FS_SIZE_INFORMATION, *PFILE_FS_SIZE_INFORMATION;
+
+typedef struct _FILE_FS_ATTRIBUTE_INFORMATION {
+ ULONG FileSystemAttributes;
+ LONG MaximumComponentNameLength;
+ ULONG FileSystemNameLength;
+ WCHAR FileSystemName[0];
+} FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION;
+
+/*
+ FileSystemAttributes is one of the following values:
+
+ FILE_CASE_SENSITIVE_SEARCH 0x00000001
+ FILE_CASE_PRESERVED_NAMES 0x00000002
+ FILE_UNICODE_ON_DISK 0x00000004
+ FILE_PERSISTENT_ACLS 0x00000008
+ FILE_FILE_COMPRESSION 0x00000010
+ FILE_VOLUME_QUOTAS 0x00000020
+ FILE_VOLUME_IS_COMPRESSED 0x00008000
+*/
+typedef struct _FILE_FS_LABEL_INFORMATION {
+ ULONG VolumeLabelLength;
+ WCHAR VolumeLabel[0];
+} FILE_FS_LABEL_INFORMATION, *PFILE_FS_LABEL_INFORMATION;
+
+// read file scatter / write file scatter
+//FIXME I am a win32 struct aswell
+
+typedef union _FILE_SEGMENT_ELEMENT {
+ PVOID Buffer;
+ ULONG Alignment;
+}FILE_SEGMENT_ELEMENT, *PFILE_SEGMENT_ELEMENT;
+
+typedef struct _FILE_DIRECTORY_INFORMATION {
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ TIME CreationTime;
+ TIME LastAccessTime;
+ TIME LastWriteTime;
+ TIME ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ WCHAR FileName[0];
+} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;
+
+typedef struct _FILE_FULL_DIRECTORY_INFORMATION {
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ TIME CreationTime;
+ TIME LastAccessTime;
+ TIME LastWriteTime;
+ TIME ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ ULONG EaSize;
+ WCHAR FileName[0]; // variable size
+} FILE_FULL_DIRECTORY_INFORMATION, *PFILE_FULL_DIRECTORY_INFORMATION,
+ FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION;
+
+
+typedef struct _FILE_BOTH_DIRECTORY_INFORMATION {
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ TIME CreationTime;
+ TIME LastAccessTime;
+ TIME LastWriteTime;
+ TIME ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ ULONG EaSize;
+ CHAR ShortNameLength;
+ WCHAR ShortName[12]; // 8.3 name
+ WCHAR FileName[0];
+} FILE_BOTH_DIRECTORY_INFORMATION, *PFILE_BOTH_DIRECTORY_INFORMATION,
+ FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;
+
+/*
+ NotifyFilter / CompletionFilter:
+
+ FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
+ FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
+ FILE_NOTIFY_CHANGE_NAME 0x00000003
+ FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004
+ FILE_NOTIFY_CHANGE_SIZE 0x00000008
+ FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
+ FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020
+ FILE_NOTIFY_CHANGE_CREATION 0x00000040
+ FILE_NOTIFY_CHANGE_EA 0x00000080
+ FILE_NOTIFY_CHANGE_SECURITY 0x00000100
+ FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200
+ FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400
+ FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
+*/
+
+typedef struct _FILE_NOTIFY_INFORMATION {
+ ULONG Action;
+ ULONG FileNameLength;
+ WCHAR FileName[0];
+} FILE_NOTIFY_INFORMATION;
+
+#define FSCTL_GET_VOLUME_BITMAP 0x9006F
+#define FSCTL_GET_RETRIEVAL_POINTERS 0x90073
+#define FSCTL_MOVE_FILE 0x90074
+
+typedef struct _MAPPING_PAIR
+{
+ ULONGLONG Vcn;
+ ULONGLONG Lcn;
+} MAPPING_PAIR, *PMAPPING_PAIR;
+
+typedef struct _GET_RETRIEVAL_DESCRIPTOR
+{
+ ULONG NumberOfPairs;
+ ULONGLONG StartVcn;
+ MAPPING_PAIR Pair[0]; // variable size
+} GET_RETRIEVAL_DESCRIPTOR, *PGET_RETRIEVAL_DESCRIPTOR;
+
+typedef struct _MOVEFILE_DESCRIPTOR
+{
+ HANDLE FileHandle;
+ ULONG Reserved;
+ LARGE_INTEGER StartVcn;
+ LARGE_INTEGER TargetLcn;
+ ULONG NumVcns;
+ ULONG Reserved1;
+} MOVEFILE_DESCRIPTOR, *PMOVEFILE_DESCRIPTOR;
+
+typedef struct _SECTION_BASIC_INFORMATION
+{
+ PVOID BaseAddress;
+ ULONG Attributes;
+ LARGE_INTEGER Size;
+} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION;
+
+typedef enum _SECTION_INFORMATION_CLASS
+{
+ SectionBasicInformation,
+ SectionImageInformation,
+} SECTION_INFORMATION_CLASS;
+
+// shutdown action
+
+typedef enum SHUTDOWN_ACTION_TAG {
+ ShutdownNoReboot,
+ ShutdownReboot,
+ ShutdownPowerOff
+} SHUTDOWN_ACTION;
+
+#else /* __USE_W32API */
+
+#define DebugDbgLoadSymbols ((DEBUG_CONTROL_CODE)0xffffffff)
+
+#endif /* __USE_W32API */
+
+#define NtCurrentProcess() ( (HANDLE) 0xFFFFFFFF )
+#define NtCurrentThread() ( (HANDLE) 0xFFFFFFFE )
+#if 1
+extern ULONG NtBuildNumber;
+#else
+#ifdef __NTOSKRNL__
+extern ULONG NtBuildNumber;
+#else
+extern ULONG NtBuildNumber;
+#endif
+#endif
+
+// event access mask
+
+#define EVENT_READ_ACCESS 1
+#define EVENT_WRITE_ACCESS 2
+
+//process query / set information class
+
+#define ProcessBasicInformation 0
+#define ProcessQuotaLimits 1
+#define ProcessIoCounters 2
+#define ProcessVmCounters 3
+#define ProcessTimes 4
+#define ProcessBasePriority 5
+#define ProcessRaisePriority 6
+#define ProcessDebugPort 7
+#define ProcessExceptionPort 8
+#define ProcessAccessToken 9
+#define ProcessLdtInformation 10
+#define ProcessLdtSize 11
+#define ProcessDefaultHardErrorMode 12
+#define ProcessIoPortHandlers 13
+#define ProcessPooledUsageAndLimits 14
+#define ProcessWorkingSetWatch 15
+#define ProcessUserModeIOPL 16
+#define ProcessEnableAlignmentFaultFixup 17
+#define ProcessPriorityClass 18
+#define ProcessWx86Information 19
+#define ProcessHandleCount 20
+#define ProcessAffinityMask 21
+#define ProcessPriorityBoost 22
+#define ProcessDeviceMap 23
+#define ProcessSessionInformation 24
+#define ProcessForegroundInformation 25
+#define ProcessWow64Information 26
+/* ReactOS private. */
+#define ProcessImageFileName 27
+#define ProcessDesktop 28
+#define MaxProcessInfoClass 29
+
+/*
+ * thread query / set information class
+ */
+#define ThreadBasicInformation 0
+#define ThreadTimes 1
+#define ThreadPriority 2
+#define ThreadBasePriority 3
+#define ThreadAffinityMask 4
+#define ThreadImpersonationToken 5
+#define ThreadDescriptorTableEntry 6
+#define ThreadEnableAlignmentFaultFixup 7
+#define ThreadEventPair 8
+#define ThreadQuerySetWin32StartAddress 9
+#define ThreadZeroTlsCell 10
+#define ThreadPerformanceCount 11
+#define ThreadAmILastThread 12
+#define ThreadIdealProcessor 13
+#define ThreadPriorityBoost 14
+#define ThreadSetTlsArrayAddress 15
+#define ThreadIsIoPending 16
+#define ThreadHideFromDebugger 17
+#define MaxThreadInfoClass 17
+
+// object handle information
+
+#define ObjectBasicInformation 0
+#define ObjectNameInformation 1
+#define ObjectTypeInformation 2
+#define ObjectAllInformation 3
+#define ObjectDataInformation 4
+
+typedef struct _ATOM_TABLE_INFORMATION
+{
+ ULONG NumberOfAtoms;
+ RTL_ATOM Atoms[1];
+} ATOM_TABLE_INFORMATION, *PATOM_TABLE_INFORMATION;
+
+
+// mutant information
+
+typedef enum _MUTANT_INFORMATION_CLASS
+{
+ MutantBasicInformation = 0
+} MUTANT_INFORMATION_CLASS;
+
+typedef struct _MUTANT_BASIC_INFORMATION
+{
+ LONG Count;
+ BOOLEAN Owned;
+ BOOLEAN Abandoned;
+} MUTANT_BASIC_INFORMATION, *PMUTANT_BASIC_INFORMATION;
+
+
+// SystemTimeOfDayInformation (3)
+typedef
+struct _SYSTEM_TIMEOFDAY_INFORMATION
+{
+ LARGE_INTEGER BootTime;
+ LARGE_INTEGER CurrentTime;
+ LARGE_INTEGER TimeZoneBias;
+ ULONG TimeZoneId;
+ ULONG Reserved;
+} SYSTEM_TIMEOFDAY_INFORMATION, *PSYSTEM_TIMEOFDAY_INFORMATION;
+
+// SystemPathInformation (4)
+// IT DOES NOT WORK
+typedef
+struct _SYSTEM_PATH_INFORMATION
+{
+ PVOID Dummy;
+
+} SYSTEM_PATH_INFORMATION, * PSYSTEM_PATH_INFORMATION;
+
+// SystemProcessInformation (5)
+typedef
+struct _SYSTEM_THREAD_INFORMATION
+{
+ TIME KernelTime;
+ TIME UserTime;
+ TIME CreateTime;
+ ULONG TickCount;
+ ULONG StartEIP;
+ CLIENT_ID ClientId;
+ ULONG DynamicPriority;
+ ULONG BasePriority;
+ ULONG nSwitches;
+ DWORD State;
+ KWAIT_REASON WaitReason;
+
+} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION;
+
+typedef
+struct SYSTEM_PROCESS_INFORMATION
+{
+ ULONG RelativeOffset;
+ ULONG ThreadCount;
+ ULONG Unused1 [6];
+ TIME CreateTime;
+ TIME UserTime;
+ TIME KernelTime;
+ UNICODE_STRING Name;
+ ULONG BasePriority;
+ ULONG ProcessId;
+ ULONG ParentProcessId;
+ ULONG HandleCount;
+ ULONG Unused2[2];
+ ULONG PeakVirtualSizeBytes;
+ ULONG TotalVirtualSizeBytes;
+ ULONG PageFaultCount;
+ ULONG PeakWorkingSetSizeBytes;
+ ULONG TotalWorkingSetSizeBytes;
+ ULONG PeakPagedPoolUsagePages;
+ ULONG TotalPagedPoolUsagePages;
+ ULONG PeakNonPagedPoolUsagePages;
+ ULONG TotalNonPagedPoolUsagePages;
+ ULONG TotalPageFileUsageBytes;
+ ULONG PeakPageFileUsageBytes;
+ ULONG TotalPrivateBytes;
+ SYSTEM_THREAD_INFORMATION ThreadSysInfo [1];
+
+} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
+
+// SystemCallCountInformation (6)
+typedef
+struct _SYSTEM_SDT_INFORMATION
+{
+ ULONG BufferLength;
+ ULONG NumberOfSystemServiceTables;
+ ULONG NumberOfServices [1];
+ ULONG ServiceCounters [1];
+
+} SYSTEM_SDT_INFORMATION, *PSYSTEM_SDT_INFORMATION;
+
+// SystemDeviceInformation (7)
+typedef
+struct _SYSTEM_DEVICE_INFORMATION
+{
+ ULONG NumberOfDisks;
+ ULONG NumberOfFloppies;
+ ULONG NumberOfCdRoms;
+ ULONG NumberOfTapes;
+ ULONG NumberOfSerialPorts;
+ ULONG NumberOfParallelPorts;
+} SYSTEM_DEVICE_INFORMATION, *PSYSTEM_DEVICE_INFORMATION;
+
+// SystemProcessorPerformanceInformation (8)
+// (one per processor in the system)
+typedef
+struct _SYSTEM_PROCESSORTIME_INFO
+{
+ TIME TotalProcessorRunTime;
+ TIME TotalProcessorTime;
+ TIME TotalProcessorUserTime;
+ TIME TotalDPCTime;
+ TIME TotalInterruptTime;
+ ULONG TotalInterrupts;
+ ULONG Unused;
+
+} SYSTEM_PROCESSORTIME_INFO, *PSYSTEM_PROCESSORTIME_INFO;
+
+// SystemFlagsInformation (9)
+typedef
+struct _SYSTEM_FLAGS_INFORMATION
+{
+ ULONG Flags;
+
+} SYSTEM_FLAGS_INFORMATION, * PSYSTEM_FLAGS_INFORMATION;
+
+#define FLG_STOP_ON_EXCEPTION 0x00000001
+#define FLG_SHOW_LDR_SNAPS 0x00000002
+#define FLG_DEBUG_INITIAL_COMMAND 0x00000004
+#define FLG_STOP_ON_HANG_GUI 0x00000008
+#define FLG_HEAP_ENABLE_TAIL_CHECK 0x00000010
+#define FLG_HEAP_ENABLE_FREE_CHECK 0x00000020
+#define FLG_HEAP_VALIDATE_PARAMETERS 0x00000040
+#define FLG_HEAP_VALIDATE_ALL 0x00000080
+#define FLG_POOL_ENABLE_TAIL_CHECK 0x00000100
+#define FLG_POOL_ENABLE_FREE_CHECK 0x00000200
+#define FLG_POOL_ENABLE_TAGGING 0x00000400
+#define FLG_HEAP_ENABLE_TAGGING 0x00000800
+#define FLG_USER_STACK_TRACE_DB 0x00001000
+#define FLG_KERNEL_STACK_TRACE_DB 0x00002000
+#define FLG_MAINTAIN_OBJECT_TYPELIST 0x00004000
+#define FLG_HEAP_ENABLE_TAG_BY_DLL 0x00008000
+#define FLG_IGNORE_DEBUG_PRIV 0x00010000
+#define FLG_ENABLE_CSRDEBUG 0x00020000
+#define FLG_ENABLE_KDEBUG_SYMBOL_LOAD 0x00040000
+#define FLG_DISABLE_PAGE_KERNEL_STACKS 0x00080000
+#define FLG_HEAP_ENABLE_CALL_TRACING 0x00100000
+#define FLG_HEAP_DISABLE_COALESCING 0x00200000
+#define FLG_ENABLE_CLOSE_EXCEPTION 0x00400000
+#define FLG_ENABLE_EXCEPTION_LOGGING 0x00800000
+#define FLG_UNKNOWN_01000000 0x01000000
+#define FLG_UNKNOWN_02000000 0x02000000
+#define FLG_UNKNOWN_04000000 0x04000000
+#define FLG_ENABLE_DBGPRINT_BUFFERING 0x08000000
+#define FLG_UNKNOWN_10000000 0x10000000
+#define FLG_UNKNOWN_20000000 0x20000000
+#define FLG_UNKNOWN_40000000 0x40000000
+#define FLG_UNKNOWN_80000000 0x80000000
+
+// SystemCallTimeInformation (10)
+// UNKNOWN
+
+// SystemLocksInformation (12)
+typedef
+struct _SYSTEM_RESOURCE_LOCK_ENTRY
+{
+ ULONG ResourceAddress;
+ ULONG Always1;
+ ULONG Unknown;
+ ULONG ActiveCount;
+ ULONG ContentionCount;
+ ULONG Unused[2];
+ ULONG NumberOfSharedWaiters;
+ ULONG NumberOfExclusiveWaiters;
+
+} SYSTEM_RESOURCE_LOCK_ENTRY, *PSYSTEM_RESOURCE_LOCK_ENTRY;
+
+typedef
+struct _SYSTEM_RESOURCE_LOCK_INFO
+{
+ ULONG Count;
+ SYSTEM_RESOURCE_LOCK_ENTRY Lock [1];
+
+} SYSTEM_RESOURCE_LOCK_INFO, *PSYSTEM_RESOURCE_LOCK_INFO;
+
+// SystemInformation13 (13)
+// UNKNOWN
+
+// SystemInformation14 (14)
+// UNKNOWN
+
+// SystemInformation15 (15)
+// UNKNOWN
+
+// SystemInstructionEmulationInfo (19)
+typedef
+struct _SYSTEM_VDM_INFORMATION
+{
+ ULONG VdmSegmentNotPresentCount;
+ ULONG VdmINSWCount;
+ ULONG VdmESPREFIXCount;
+ ULONG VdmCSPREFIXCount;
+ ULONG VdmSSPREFIXCount;
+ ULONG VdmDSPREFIXCount;
+ ULONG VdmFSPREFIXCount;
+ ULONG VdmGSPREFIXCount;
+ ULONG VdmOPER32PREFIXCount;
+ ULONG VdmADDR32PREFIXCount;
+ ULONG VdmINSBCount;
+ ULONG VdmINSWV86Count;
+ ULONG VdmOUTSBCount;
+ ULONG VdmOUTSWCount;
+ ULONG VdmPUSHFCount;
+ ULONG VdmPOPFCount;
+ ULONG VdmINTNNCount;
+ ULONG VdmINTOCount;
+ ULONG VdmIRETCount;
+ ULONG VdmINBIMMCount;
+ ULONG VdmINWIMMCount;
+ ULONG VdmOUTBIMMCount;
+ ULONG VdmOUTWIMMCount;
+ ULONG VdmINBCount;
+ ULONG VdmINWCount;
+ ULONG VdmOUTBCount;
+ ULONG VdmOUTWCount;
+ ULONG VdmLOCKPREFIXCount;
+ ULONG VdmREPNEPREFIXCount;
+ ULONG VdmREPPREFIXCount;
+ ULONG VdmHLTCount;
+ ULONG VdmCLICount;
+ ULONG VdmSTICount;
+ ULONG VdmBopCount;
+
+} SYSTEM_VDM_INFORMATION, *PSYSTEM_VDM_INFORMATION;
+
+// SystemInformation20 (20)
+// UNKNOWN
+
+// SystemPoolTagInformation (22)
+// found by Klaus P. Gerlicher
+// (implemented only in checked builds)
+typedef
+struct _POOL_TAG_STATS
+{
+ ULONG AllocationCount;
+ ULONG FreeCount;
+ ULONG SizeBytes;
+
+} POOL_TAG_STATS;
+
+typedef
+struct _SYSTEM_POOL_TAG_ENTRY
+{
+ ULONG Tag;
+ POOL_TAG_STATS Paged;
+ POOL_TAG_STATS NonPaged;
+
+} SYSTEM_POOL_TAG_ENTRY, * PSYSTEM_POOL_TAG_ENTRY;
+
+typedef
+struct _SYSTEM_POOL_TAG_INFO
+{
+ ULONG Count;
+ SYSTEM_POOL_TAG_ENTRY PoolEntry [1];
+
+} SYSTEM_POOL_TAG_INFO, *PSYSTEM_POOL_TAG_INFO;
+
+// SystemProcessorScheduleInfo (23)
+typedef
+struct _SYSTEM_PROCESSOR_SCHEDULE_INFO
+{
+ ULONG nContextSwitches;
+ ULONG nDPCQueued;
+ ULONG nDPCRate;
+ ULONG TimerResolution;
+ ULONG nDPCBypasses;
+ ULONG nAPCBypasses;
+
+} SYSTEM_PROCESSOR_SCHEDULE_INFO, *PSYSTEM_PROCESSOR_SCHEDULE_INFO;
+
+// SystemInformation25 (25)
+// UNKNOWN
+
+// SystemProcessorFaultCountInfo (33)
+typedef
+struct _SYSTEM_PROCESSOR_FAULT_INFO
+{
+ ULONG nAlignmentFixup;
+ ULONG nExceptionDispatches;
+ ULONG nFloatingEmulation;
+ ULONG Unknown;
+
+} SYSTEM_PROCESSOR_FAULT_INFO, *PSYSTEM_PROCESSOR_FAULT_INFO;
+
+// SystemCrashDumpStateInfo (34)
+//
+
+// SystemDebuggerInformation (35)
+typedef
+struct _SYSTEM_DEBUGGER_INFO
+{
+ BOOLEAN KdDebuggerEnabled;
+ BOOLEAN KdDebuggerPresent;
+
+} SYSTEM_DEBUGGER_INFO, *PSYSTEM_DEBUGGER_INFO;
+
+// SystemInformation36 (36)
+// UNKNOWN
+
+// SystemQuotaInformation (37)
+typedef
+struct _SYSTEM_QUOTA_INFORMATION
+{
+ ULONG CmpGlobalQuota;
+ ULONG CmpGlobalQuotaUsed;
+ ULONG MmSizeofPagedPoolInBytes;
+
+} SYSTEM_QUOTA_INFORMATION, *PSYSTEM_QUOTA_INFORMATION;
+
+// (49)
+// UNKNOWN
+
+// SystemVerifierInformation (51)
+// UNKNOWN
+
+// SystemAddVerifier (52)
+// UNKNOWN
+
+// wait type
+
+#define WaitAll 0
+#define WaitAny 1
+
+// number of wait objects
+
+#define THREAD_WAIT_OBJECTS 3
+//#define MAXIMUM_WAIT_OBJECTS 64
+
+// key restore flags
+
+#define REG_WHOLE_HIVE_VOLATILE 1
+#define REG_REFRESH_HIVE 2
+
+// object type access rights
+
+#define OBJECT_TYPE_CREATE 0x0001
+#define OBJECT_TYPE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1)
+
+// directory access rights
+
+#define DIRECTORY_QUERY 0x0001
+#define DIRECTORY_TRAVERSE 0x0002
+#define DIRECTORY_CREATE_OBJECT 0x0004
+#define DIRECTORY_CREATE_SUBDIRECTORY 0x0008
+
+#define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0xF)
+
+// symbolic link access rights
+
+#define SYMBOLIC_LINK_QUERY 0x0001
+#define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1)
+
+
+typedef struct _OBJECT_DATA_INFORMATION
+{
+ BOOLEAN bInheritHandle;
+ BOOLEAN bProtectFromClose;
+} OBJECT_DATA_INFORMATION, *POBJECT_DATA_INFORMATION;
+
+
+typedef struct _OBJECT_TYPE_INFORMATION
+{
+ UNICODE_STRING Name;
+ UNICODE_STRING Type;
+ ULONG TotalHandles;
+ ULONG ReferenceCount;
+} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
+
+
+// directory information
+
+typedef struct _OBJDIR_INFORMATION {
+ UNICODE_STRING ObjectName;
+ UNICODE_STRING ObjectTypeName; // Directory, Device ...
+ UCHAR Data[0];
+} OBJDIR_INFORMATION, *POBJDIR_INFORMATION;
+
+
+/*
+ Action is one of the following values:
+
+ FILE_ACTION_ADDED 0x00000001
+ FILE_ACTION_REMOVED 0x00000002
+ FILE_ACTION_MODIFIED 0x00000003
+ FILE_ACTION_RENAMED_OLD_NAME 0x00000004
+ FILE_ACTION_RENAMED_NEW_NAME 0x00000005
+ FILE_ACTION_ADDED_STREAM 0x00000006
+ FILE_ACTION_REMOVED_STREAM 0x00000007
+ FILE_ACTION_MODIFIED_STREAM 0x00000008
+
+*/
+
+
+// File System Control commands ( related to defragging )
+
+#define FSCTL_READ_MFT_RECORD 0x90068 // NTFS only
+
+typedef struct _BITMAP_DESCRIPTOR
+{
+ ULONGLONG StartLcn;
+ ULONGLONG ClustersToEndOfVol;
+ BYTE Map[0]; // variable size
+} BITMAP_DESCRIPTOR, *PBITMAP_DESCRIPTOR;
+
+
+//typedef enum _TIMER_TYPE
+//{
+// NotificationTimer,
+// SynchronizationTimer
+//} TIMER_TYPE;
+
+typedef struct _TIMER_BASIC_INFORMATION
+{
+ LARGE_INTEGER TimeRemaining;
+ BOOLEAN SignalState;
+} TIMER_BASIC_INFORMATION, *PTIMER_BASIC_INFORMATION;
+
+typedef enum _TIMER_INFORMATION_CLASS
+{
+ TimerBasicInformation
+} TIMER_INFORMATION_CLASS;
+
+typedef
+struct _LPC_PORT_BASIC_INFORMATION
+{
+ DWORD Unknown0;
+ DWORD Unknown1;
+ DWORD Unknown2;
+ DWORD Unknown3;
+ DWORD Unknown4;
+ DWORD Unknown5;
+ DWORD Unknown6;
+ DWORD Unknown7;
+ DWORD Unknown8;
+ DWORD Unknown9;
+ DWORD Unknown10;
+ DWORD Unknown11;
+ DWORD Unknown12;
+ DWORD Unknown13;
+
+} LPC_PORT_BASIC_INFORMATION, * PLPC_PORT_BASIC_INFORMATION;
+
+#endif
--- /dev/null
+/*
+ * Common controls definitions
+ *
+ * Copyright (C) the Wine project
+ *
+ * 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
+ */
+
+#ifndef __WINE_COMMCTRL_H
+#define __WINE_COMMCTRL_H
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winnls.h"
+#include "prsht.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GetWindowWord GetWindowLongA
+
+/* Macros to map Winelib names to the correct implementation name */
+/* depending on __WINE__ and UNICODE macros. */
+/* Note that Winelib is purely Win32. */
+
+#ifdef __WINE__
+# define WINELIB_NAME_AW(func) \
+ func##_must_be_suffixed_with_W_or_A_in_this_context \
+ func##_must_be_suffixed_with_W_or_A_in_this_context
+#else /* __WINE__ */
+# ifdef UNICODE
+# define WINELIB_NAME_AW(func) func##W
+# else
+# define WINELIB_NAME_AW(func) func##A
+# endif /* UNICODE */
+#endif /* __WINE__ */
+
+#ifdef __WINE__
+# define DECL_WINELIB_TYPE_AW(type) /* nothing */
+#else /* __WINE__ */
+# define DECL_WINELIB_TYPE_AW(type) typedef WINELIB_NAME_AW(type) type;
+#endif /* __WINE__ */
+
+
+
+BOOL WINAPI ShowHideMenuCtl (HWND, UINT, LPINT);
+VOID WINAPI GetEffectiveClientRect (HWND, LPRECT, LPINT);
+VOID WINAPI InitCommonControls (VOID);
+
+typedef struct tagINITCOMMONCONTROLSEX {
+ DWORD dwSize;
+ DWORD dwICC;
+} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;
+
+BOOL WINAPI InitCommonControlsEx (LPINITCOMMONCONTROLSEX);
+
+LANGID WINAPI GetMUILanguage (VOID);
+VOID WINAPI InitMUILanguage (LANGID uiLang);
+
+
+#define COMCTL32_VERSION 5 /* dll version */
+
+#ifndef _WIN32_IE
+#define _WIN32_IE 0x0400
+#endif
+
+#define ICC_LISTVIEW_CLASSES 0x00000001 /* listview, header */
+#define ICC_TREEVIEW_CLASSES 0x00000002 /* treeview, tooltips */
+#define ICC_BAR_CLASSES 0x00000004 /* toolbar, statusbar, trackbar, tooltips */
+#define ICC_TAB_CLASSES 0x00000008 /* tab, tooltips */
+#define ICC_UPDOWN_CLASS 0x00000010 /* updown */
+#define ICC_PROGRESS_CLASS 0x00000020 /* progress */
+#define ICC_HOTKEY_CLASS 0x00000040 /* hotkey */
+#define ICC_ANIMATE_CLASS 0x00000080 /* animate */
+#define ICC_WIN95_CLASSES 0x000000FF
+#define ICC_DATE_CLASSES 0x00000100 /* month picker, date picker, time picker, updown */
+#define ICC_USEREX_CLASSES 0x00000200 /* comboex */
+#define ICC_COOL_CLASSES 0x00000400 /* rebar (coolbar) */
+#define ICC_INTERNET_CLASSES 0x00000800 /* IP address, ... */
+#define ICC_PAGESCROLLER_CLASS 0x00001000 /* page scroller */
+#define ICC_NATIVEFNTCTL_CLASS 0x00002000 /* native font control ???*/
+
+
+/* common control styles */
+#define CCS_TOP 0x00000001L
+#define CCS_NOMOVEY 0x00000002L
+#define CCS_BOTTOM 0x00000003L
+#define CCS_NORESIZE 0x00000004L
+#define CCS_NOPARENTALIGN 0x00000008L
+#define CCS_ADJUSTABLE 0x00000020L
+#define CCS_NODIVIDER 0x00000040L
+#define CCS_VERT 0x00000080L
+#define CCS_LEFT (CCS_VERT|CCS_TOP)
+#define CCS_RIGHT (CCS_VERT|CCS_BOTTOM)
+#define CCS_NOMOVEX (CCS_VERT|CCS_NOMOVEY)
+
+
+/* common control shared messages */
+#define CCM_FIRST 0x2000
+
+#define CCM_SETBKCOLOR (CCM_FIRST+1) /* lParam = bkColor */
+#define CCM_SETCOLORSCHEME (CCM_FIRST+2) /* lParam = COLORSCHEME struct ptr */
+#define CCM_GETCOLORSCHEME (CCM_FIRST+3) /* lParam = COLORSCHEME struct ptr */
+#define CCM_GETDROPTARGET (CCM_FIRST+4)
+#define CCM_SETUNICODEFORMAT (CCM_FIRST+5)
+#define CCM_GETUNICODEFORMAT (CCM_FIRST+6)
+#define CCM_SETVERSION (CCM_FIRST+7)
+#define CCM_GETVERSION (CCM_FIRST+8)
+#define CCM_SETNOTIFYWINDOW (CCM_FIRST+9) /* wParam = hwndParent */
+
+
+/* common notification codes (WM_NOTIFY)*/
+#define NM_FIRST (0U- 0U)
+#define NM_LAST (0U- 99U)
+#define NM_OUTOFMEMORY (NM_FIRST-1)
+#define NM_CLICK (NM_FIRST-2)
+#define NM_DBLCLK (NM_FIRST-3)
+#define NM_RETURN (NM_FIRST-4)
+#define NM_RCLICK (NM_FIRST-5)
+#define NM_RDBLCLK (NM_FIRST-6)
+#define NM_SETFOCUS (NM_FIRST-7)
+#define NM_KILLFOCUS (NM_FIRST-8)
+#define NM_CUSTOMDRAW (NM_FIRST-12)
+#define NM_HOVER (NM_FIRST-13)
+#define NM_NCHITTEST (NM_FIRST-14)
+#define NM_KEYDOWN (NM_FIRST-15)
+#define NM_RELEASEDCAPTURE (NM_FIRST-16)
+#define NM_SETCURSOR (NM_FIRST-17)
+#define NM_CHAR (NM_FIRST-18)
+#define NM_TOOLTIPSCREATED (NM_FIRST-19)
+
+#define HANDLE_WM_NOTIFY(hwnd, wParam, lParam, fn) \
+ (fn)((hwnd), (int)(wParam), (NMHDR*)(lParam))
+#define FORWARD_WM_NOTIFY(hwnd, idFrom, pnmhdr, fn) \
+ (LRESULT)(fn)((hwnd), WM_NOTIFY, (WPARAM)(int)(idFrom), (LPARAM)(NMHDR*)(pnmhdr))
+
+
+/* callback constants */
+#define LPSTR_TEXTCALLBACKA ((LPSTR)-1L)
+#define LPSTR_TEXTCALLBACKW ((LPWSTR)-1L)
+#define LPSTR_TEXTCALLBACK WINELIB_NAME_AW(LPSTR_TEXTCALLBACK)
+
+#define I_IMAGECALLBACK (-1)
+#define I_IMAGENONE (-2)
+#define I_INDENTCALLBACK (-1)
+#define I_CHILDRENCALLBACK (-1)
+
+/* owner drawn types */
+#define ODT_HEADER 100
+#define ODT_TAB 101
+#define ODT_LISTVIEW 102
+
+/* common notification structures */
+typedef struct tagNMTOOLTIPSCREATED
+{
+ NMHDR hdr;
+ HWND hwndToolTips;
+} NMTOOLTIPSCREATED, *LPNMTOOLTIPSCREATED;
+
+typedef struct tagNMMOUSE
+{
+ NMHDR hdr;
+ DWORD dwItemSpec;
+ DWORD dwItemData;
+ POINT pt;
+ DWORD dwHitInfo; /* info where on item or control the mouse is */
+} NMMOUSE, *LPNMMOUSE;
+
+typedef struct tagNMOBJECTNOTIFY
+{
+ NMHDR hdr;
+ int iItem;
+#ifdef __IID_DEFINED__
+ const IID *piid;
+#else
+ const void *piid;
+#endif
+ void *pObject;
+ HRESULT hResult;
+ DWORD dwFlags;
+} NMOBJECTNOTIFY, *LPNMOBJECTNOTIFY;
+
+typedef struct tagNMKEY
+{
+ NMHDR hdr;
+ UINT nVKey;
+ UINT uFlags;
+} NMKEY, *LPNMKEY;
+
+typedef struct tagNMCHAR
+{
+ NMHDR hdr;
+ UINT ch;
+ DWORD dwItemPrev; /* Item previously selected */
+ DWORD dwItemNext; /* Item to be selected */
+} NMCHAR, *LPNMCHAR;
+
+#ifndef CCSIZEOF_STRUCT
+#define CCSIZEOF_STRUCT(name, member) \
+ (((INT)((LPBYTE)(&((name*)0)->member)-((LPBYTE)((name*)0))))+ \
+ sizeof(((name*)0)->member))
+#endif
+
+
+/* This is only for Winelib applications. DON't use it wine itself!!! */
+#ifndef SNDMSG
+#ifdef __cplusplus
+#define SNDMSG ::SendMessage
+#else /* __cplusplus */
+#define SNDMSG SendMessage
+#endif /* __cplusplus */
+#endif /* SNDMSG */
+
+
+#ifdef __cplusplus
+#define SNDMSGA ::SendMessageA
+#define SNDMSGW ::SendMessageW
+#else
+#define SNDMSGA SendMessageA
+#define SNDMSGW SendMessageW
+#endif
+
+/* Custom Draw messages */
+
+#define CDRF_DODEFAULT 0x0
+#define CDRF_NEWFONT 0x00000002
+#define CDRF_SKIPDEFAULT 0x00000004
+#define CDRF_NOTIFYPOSTPAINT 0x00000010
+#define CDRF_NOTIFYITEMDRAW 0x00000020
+#define CDRF_NOTIFYSUBITEMDRAW 0x00000020
+#define CDRF_NOTIFYPOSTERASE 0x00000040
+#define CDRF_NOTIFYITEMERASE 0x00000080 /* obsolete ??? */
+
+
+/* drawstage flags */
+
+#define CDDS_PREPAINT 1
+#define CDDS_POSTPAINT 2
+#define CDDS_PREERASE 3
+#define CDDS_POSTERASE 4
+
+#define CDDS_ITEM 0x00010000
+#define CDDS_ITEMPREPAINT (CDDS_ITEM | CDDS_PREPAINT)
+#define CDDS_ITEMPOSTPAINT (CDDS_ITEM | CDDS_POSTPAINT)
+#define CDDS_ITEMPREERASE (CDDS_ITEM | CDDS_PREERASE)
+#define CDDS_ITEMPOSTERASE (CDDS_ITEM | CDDS_POSTERASE)
+#define CDDS_SUBITEM 0x00020000
+
+/* itemState flags */
+
+#define CDIS_SELECTED 0x0001
+#define CDIS_GRAYED 0x0002
+#define CDIS_DISABLED 0x0004
+#define CDIS_CHECKED 0x0008
+#define CDIS_FOCUS 0x0010
+#define CDIS_DEFAULT 0x0020
+#define CDIS_HOT 0x0040
+#define CDIS_MARKED 0x0080
+#define CDIS_INDETERMINATE 0x0100
+
+
+typedef struct tagNMCUSTOMDRAWINFO
+{
+ NMHDR hdr;
+ DWORD dwDrawStage;
+ HDC hdc;
+ RECT rc;
+ DWORD dwItemSpec;
+ UINT uItemState;
+ LPARAM lItemlParam;
+} NMCUSTOMDRAW, *LPNMCUSTOMDRAW;
+
+typedef struct tagNMTTCUSTOMDRAW
+{
+ NMCUSTOMDRAW nmcd;
+ UINT uDrawFlags;
+} NMTTCUSTOMDRAW, *LPNMTTCUSTOMDRAW;
+
+
+
+
+/* StatusWindow */
+
+#define STATUSCLASSNAME16 "msctls_statusbar"
+#define STATUSCLASSNAMEA "msctls_statusbar32"
+#if defined(__GNUC__)
+# define STATUSCLASSNAMEW (const WCHAR []){ 'm','s','c','t','l','s','_', \
+ 's','t','a','t','u','s','b','a','r','3','2',0 }
+#elif defined(_MSC_VER)
+# define STATUSCLASSNAMEW L"msctls_statusbar32"
+#else
+static const WCHAR STATUSCLASSNAMEW[] = { 'm','s','c','t','l','s','_',
+ 's','t','a','t','u','s','b','a','r','3','2',0 };
+#endif
+#define STATUSCLASSNAME WINELIB_NAME_AW(STATUSCLASSNAME)
+
+#define SBT_NOBORDERS 0x0100
+#define SBT_POPOUT 0x0200
+#define SBT_RTLREADING 0x0400 /* not supported */
+#define SBT_TOOLTIPS 0x0800
+#define SBT_OWNERDRAW 0x1000
+
+#define SBARS_SIZEGRIP 0x0100
+
+#define SB_SETTEXTA (WM_USER+1)
+#define SB_SETTEXTW (WM_USER+11)
+#define SB_SETTEXT WINELIB_NAME_AW(SB_SETTEXT)
+#define SB_GETTEXTA (WM_USER+2)
+#define SB_GETTEXTW (WM_USER+13)
+#define SB_GETTEXT WINELIB_NAME_AW(SB_GETTEXT)
+#define SB_GETTEXTLENGTHA (WM_USER+3)
+#define SB_GETTEXTLENGTHW (WM_USER+12)
+#define SB_GETTEXTLENGTH WINELIB_NAME_AW(SB_GETTEXTLENGTH)
+#define SB_SETPARTS (WM_USER+4)
+#define SB_SETBORDERS (WM_USER+5)
+#define SB_GETPARTS (WM_USER+6)
+#define SB_GETBORDERS (WM_USER+7)
+#define SB_SETMINHEIGHT (WM_USER+8)
+#define SB_SIMPLE (WM_USER+9)
+#define SB_GETRECT (WM_USER+10)
+#define SB_ISSIMPLE (WM_USER+14)
+#define SB_SETICON (WM_USER+15)
+#define SB_SETTIPTEXTA (WM_USER+16)
+#define SB_SETTIPTEXTW (WM_USER+17)
+#define SB_SETTIPTEXT WINELIB_NAME_AW(SB_SETTIPTEXT)
+#define SB_GETTIPTEXTA (WM_USER+18)
+#define SB_GETTIPTEXTW (WM_USER+19)
+#define SB_GETTIPTEXT WINELIB_NAME_AW(SB_GETTIPTEXT)
+#define SB_GETICON (WM_USER+20)
+#define SB_SETBKCOLOR CCM_SETBKCOLOR /* lParam = bkColor */
+#define SB_GETUNICODEFORMAT CCM_GETUNICODEFORMAT
+#define SB_SETUNICODEFORMAT CCM_SETUNICODEFORMAT
+
+#define SBN_FIRST (0U-880U)
+#define SBN_LAST (0U-899U)
+#define SBN_SIMPLEMODECHANGE (SBN_FIRST-0)
+
+HWND WINAPI CreateStatusWindowA (INT, LPCSTR, HWND, UINT);
+HWND WINAPI CreateStatusWindowW (INT, LPCWSTR, HWND, UINT);
+#define CreateStatusWindow WINELIB_NAME_AW(CreateStatusWindow)
+VOID WINAPI DrawStatusTextA (HDC, LPRECT, LPCSTR, UINT);
+VOID WINAPI DrawStatusTextW (HDC, LPRECT, LPCWSTR, UINT);
+#define DrawStatusText WINELIB_NAME_AW(DrawStatusText)
+VOID WINAPI MenuHelp (UINT, WPARAM, LPARAM, HMENU,
+ HINSTANCE, HWND, UINT*);
+
+typedef struct tagCOLORSCHEME
+{
+ DWORD dwSize;
+ COLORREF clrBtnHighlight; /* highlight color */
+ COLORREF clrBtnShadow; /* shadow color */
+} COLORSCHEME, *LPCOLORSCHEME;
+
+/**************************************************************************
+ * Drag List control
+ */
+
+typedef struct tagDRAGLISTINFO
+{
+ UINT uNotification;
+ HWND hWnd;
+ POINT ptCursor;
+} DRAGLISTINFO, *LPDRAGLISTINFO;
+
+#define DL_BEGINDRAG (WM_USER+133)
+#define DL_DRAGGING (WM_USER+134)
+#define DL_DROPPED (WM_USER+135)
+#define DL_CANCELDRAG (WM_USER+136)
+
+#define DL_CURSORSET 0
+#define DL_STOPCURSOR 1
+#define DL_COPYCURSOR 2
+#define DL_MOVECURSOR 3
+
+#define DRAGLISTMSGSTRING TEXT("commctrl_DragListMsg")
+
+BOOL WINAPI MakeDragList (HWND);
+VOID WINAPI DrawInsert (HWND, HWND, INT);
+INT WINAPI LBItemFromPt (HWND, POINT, BOOL);
+
+
+/* UpDown */
+
+#define UPDOWN_CLASS16 "msctls_updown"
+#define UPDOWN_CLASSA "msctls_updown32"
+#if defined(__GNUC__)
+# define UPDOWN_CLASSW (const WCHAR []){ 'm','s','c','t','l','s','_', \
+ 'u','p','d','o','w','n','3','2',0 }
+#elif defined(_MSC_VER)
+# define UPDOWN_CLASSW L"msctls_updown32"
+#else
+static const WCHAR UPDOWN_CLASSW[] = { 'm','s','c','t','l','s','_',
+ 'u','p','d','o','w','n','3','2',0 };
+#endif
+#define UPDOWN_CLASS WINELIB_NAME_AW(UPDOWN_CLASS)
+
+typedef struct tagUDACCEL
+{
+ UINT nSec;
+ UINT nInc;
+} UDACCEL, *LPUDACCEL;
+
+#define UD_MAXVAL 0x7fff
+#define UD_MINVAL 0x8001
+
+#define UDS_WRAP 0x0001
+#define UDS_SETBUDDYINT 0x0002
+#define UDS_ALIGNRIGHT 0x0004
+#define UDS_ALIGNLEFT 0x0008
+#define UDS_AUTOBUDDY 0x0010
+#define UDS_ARROWKEYS 0x0020
+#define UDS_HORZ 0x0040
+#define UDS_NOTHOUSANDS 0x0080
+#define UDS_HOTTRACK 0x0100
+
+#define UDN_FIRST (0U-721)
+#define UDN_LAST (0U-740)
+#define UDN_DELTAPOS (UDN_FIRST-1)
+
+#define UDM_SETRANGE (WM_USER+101)
+#define UDM_GETRANGE (WM_USER+102)
+#define UDM_SETPOS (WM_USER+103)
+#define UDM_GETPOS (WM_USER+104)
+#define UDM_SETBUDDY (WM_USER+105)
+#define UDM_GETBUDDY (WM_USER+106)
+#define UDM_SETACCEL (WM_USER+107)
+#define UDM_GETACCEL (WM_USER+108)
+#define UDM_SETBASE (WM_USER+109)
+#define UDM_GETBASE (WM_USER+110)
+#define UDM_SETRANGE32 (WM_USER+111)
+#define UDM_GETRANGE32 (WM_USER+112)
+#define UDM_SETUNICODEFORMAT CCM_SETUNICODEFORMAT
+#define UDM_GETUNICODEFORMAT CCM_GETUNICODEFORMAT
+#define UDM_SETPOS32 (WM_USER+113)
+#define UDM_GETPOS32 (WM_USER+114)
+
+
+#define NMUPDOWN NM_UPDOWN
+#define LPNMUPDOWN LPNM_UPDOWN
+
+typedef struct tagNM_UPDOWN
+{
+ NMHDR hdr;
+ int iPos;
+ int iDelta;
+} NM_UPDOWN, *LPNM_UPDOWN;
+
+HWND WINAPI CreateUpDownControl (DWORD, INT, INT, INT, INT,
+ HWND, INT, HINSTANCE, HWND,
+ INT, INT, INT);
+
+/* Progress Bar */
+
+#define PROGRESS_CLASS16 "msctls_progress"
+#define PROGRESS_CLASSA "msctls_progress32"
+#if defined(__GNUC__)
+# define PROGRESS_CLASSW (const WCHAR []){ 'm','s','c','t','l','s','_', \
+ 'p','r','o','g','r','e','s','s','3','2',0 }
+#elif defined(_MSC_VER)
+# define PROGRESS_CLASSW L"msctls_progress32"
+#else
+static const WCHAR PROGRESS_CLASSW[] = { 'm','s','c','t','l','s','_',
+ 'p','r','o','g','r','e','s','s','3','2',0 };
+#endif
+#define PROGRESS_CLASS WINELIB_NAME_AW(PROGRESS_CLASS)
+
+#define PBM_SETRANGE (WM_USER+1)
+#define PBM_SETPOS (WM_USER+2)
+#define PBM_DELTAPOS (WM_USER+3)
+#define PBM_SETSTEP (WM_USER+4)
+#define PBM_STEPIT (WM_USER+5)
+#define PBM_SETRANGE32 (WM_USER+6)
+#define PBM_GETRANGE (WM_USER+7)
+#define PBM_GETPOS (WM_USER+8)
+#define PBM_SETBARCOLOR (WM_USER+9)
+#define PBM_SETBKCOLOR CCM_SETBKCOLOR
+
+#define PBS_SMOOTH 0x01
+#define PBS_VERTICAL 0x04
+
+typedef struct
+{
+ INT iLow;
+ INT iHigh;
+} PBRANGE, *PPBRANGE;
+
+
+/* ImageList */
+
+struct _IMAGELIST;
+typedef struct _IMAGELIST *HIMAGELIST;
+
+#ifndef CLR_NONE
+#define CLR_NONE 0xFFFFFFFF
+#endif
+
+#ifndef CLR_DEFAULT
+#define CLR_DEFAULT 0xFF000000
+#endif
+
+#define CLR_HILIGHT CLR_DEFAULT
+
+#define ILC_MASK 0x0001
+#define ILC_COLOR 0x0000
+#define ILC_COLORDDB 0x00FE
+#define ILC_COLOR4 0x0004
+#define ILC_COLOR8 0x0008
+#define ILC_COLOR16 0x0010
+#define ILC_COLOR24 0x0018
+#define ILC_COLOR32 0x0020
+#define ILC_PALETTE 0x0800 /* no longer supported by M$ */
+
+#define ILD_NORMAL 0x0000
+#define ILD_TRANSPARENT 0x0001
+#define ILD_BLEND25 0x0002
+#define ILD_BLEND50 0x0004
+#define ILD_MASK 0x0010
+#define ILD_IMAGE 0x0020
+#define ILD_ROP 0x0040
+#define ILD_OVERLAYMASK 0x0F00
+#define ILD_PRESERVEALPHA 0x1000
+#define ILD_SCALE 0x2000
+#define ILD_DPISCALE 0x4000
+
+#define ILD_SELECTED ILD_BLEND50
+#define ILD_FOCUS ILD_BLEND25
+#define ILD_BLEND ILD_BLEND50
+
+#define INDEXTOOVERLAYMASK(i) ((i)<<8)
+#define INDEXTOSTATEIMAGEMASK(i) ((i)<<12)
+
+#define ILCF_MOVE (0x00000000)
+#define ILCF_SWAP (0x00000001)
+
+#define ILS_NORMAL 0x0000
+#define ILS_GLOW 0x0001
+#define ILS_SHADOW 0x0002
+#define ILS_SATURATE 0x0004
+#define ILS_ALPHA 0x0008
+
+typedef struct _IMAGEINFO
+{
+ HBITMAP hbmImage;
+ HBITMAP hbmMask;
+ INT Unused1;
+ INT Unused2;
+ RECT rcImage;
+} IMAGEINFO, *LPIMAGEINFO;
+
+
+typedef struct _IMAGELISTDRAWPARAMS
+{
+ DWORD cbSize;
+ HIMAGELIST himl;
+ INT i;
+ HDC hdcDst;
+ INT x;
+ INT y;
+ INT cx;
+ INT cy;
+ INT xBitmap; /* x offest from the upperleft of bitmap */
+ INT yBitmap; /* y offset from the upperleft of bitmap */
+ COLORREF rgbBk;
+ COLORREF rgbFg;
+ UINT fStyle;
+ DWORD dwRop;
+ DWORD fState;
+ DWORD Frame;
+ DWORD crEffect;
+} IMAGELISTDRAWPARAMS, *LPIMAGELISTDRAWPARAMS;
+
+
+INT WINAPI ImageList_Add(HIMAGELIST,HBITMAP,HBITMAP);
+INT WINAPI ImageList_AddIcon (HIMAGELIST, HICON);
+INT WINAPI ImageList_AddMasked(HIMAGELIST,HBITMAP,COLORREF);
+BOOL WINAPI ImageList_BeginDrag(HIMAGELIST,INT,INT,INT);
+BOOL WINAPI ImageList_Copy(HIMAGELIST,INT,HIMAGELIST,INT,INT);
+HIMAGELIST WINAPI ImageList_Create(INT,INT,UINT,INT,INT);
+BOOL WINAPI ImageList_Destroy(HIMAGELIST);
+BOOL WINAPI ImageList_DragEnter(HWND,INT,INT);
+BOOL WINAPI ImageList_DragLeave(HWND);
+BOOL WINAPI ImageList_DragMove(INT,INT);
+BOOL WINAPI ImageList_DragShowNolock (BOOL);
+BOOL WINAPI ImageList_Draw(HIMAGELIST,INT,HDC,INT,INT,UINT);
+BOOL WINAPI ImageList_DrawEx(HIMAGELIST,INT,HDC,INT,INT,INT,
+ INT,COLORREF,COLORREF,UINT);
+BOOL WINAPI ImageList_DrawIndirect(IMAGELISTDRAWPARAMS*);
+HIMAGELIST WINAPI ImageList_Duplicate(HIMAGELIST);
+BOOL WINAPI ImageList_EndDrag(VOID);
+COLORREF WINAPI ImageList_GetBkColor(HIMAGELIST);
+HIMAGELIST WINAPI ImageList_GetDragImage(POINT*,POINT*);
+HICON WINAPI ImageList_GetIcon(HIMAGELIST,INT,UINT);
+BOOL WINAPI ImageList_GetIconSize(HIMAGELIST,INT*,INT*);
+INT WINAPI ImageList_GetImageCount(HIMAGELIST);
+BOOL WINAPI ImageList_GetImageInfo(HIMAGELIST,INT,IMAGEINFO*);
+BOOL WINAPI ImageList_GetImageRect(HIMAGELIST,INT,LPRECT);
+HIMAGELIST WINAPI ImageList_LoadImageA(HINSTANCE,LPCSTR,INT,INT,
+ COLORREF,UINT,UINT);
+HIMAGELIST WINAPI ImageList_LoadImageW(HINSTANCE,LPCWSTR,INT,INT,
+ COLORREF,UINT,UINT);
+#define ImageList_LoadImage WINELIB_NAME_AW(ImageList_LoadImage)
+HIMAGELIST WINAPI ImageList_Merge(HIMAGELIST,INT,HIMAGELIST,INT,INT,INT);
+#ifdef IStream_IMETHODS
+HIMAGELIST WINAPI ImageList_Read(LPSTREAM);
+#endif
+BOOL WINAPI ImageList_Remove(HIMAGELIST,INT);
+BOOL WINAPI ImageList_Replace(HIMAGELIST,INT,HBITMAP,HBITMAP);
+INT WINAPI ImageList_ReplaceIcon(HIMAGELIST,INT,HICON);
+COLORREF WINAPI ImageList_SetBkColor(HIMAGELIST,COLORREF);
+BOOL WINAPI ImageList_SetDragCursorImage(HIMAGELIST,INT,INT,INT);
+
+BOOL WINAPI ImageList_SetIconSize(HIMAGELIST,INT,INT);
+BOOL WINAPI ImageList_SetImageCount(HIMAGELIST,INT);
+BOOL WINAPI ImageList_SetOverlayImage(HIMAGELIST,INT,INT);
+#ifdef IStream_IMETHODS
+BOOL WINAPI ImageList_Write(HIMAGELIST, LPSTREAM);
+#endif
+
+#ifndef __WINE__
+#define ImageList_AddIcon(himl,hicon) ImageList_ReplaceIcon(himl,-1,hicon)
+#endif
+#define ImageList_ExtractIcon(hi,himl,i) ImageList_GetIcon(himl,i,0)
+#define ImageList_LoadBitmap(hi,lpbmp,cx,cGrow,crMask) \
+ ImageList_LoadImage(hi,lpbmp,cx,cGrow,crMask,IMAGE_BITMAP,0)
+#define ImageList_RemoveAll(himl) ImageList_Remove(himl,-1)
+
+
+#ifndef WM_MOUSEHOVER
+#define WM_MOUSEHOVER 0x02A1
+#define WM_MOUSELEAVE 0x02A3
+#endif
+
+#ifndef TME_HOVER
+
+#define TME_HOVER 0x00000001
+#define TME_LEAVE 0x00000002
+#define TME_QUERY 0x40000000
+#define TME_CANCEL 0x80000000
+
+
+#define HOVER_DEFAULT 0xFFFFFFFF
+
+typedef struct tagTRACKMOUSEEVENT {
+ DWORD cbSize;
+ DWORD dwFlags;
+ HWND hwndTrack;
+ DWORD dwHoverTime;
+} TRACKMOUSEEVENT, *LPTRACKMOUSEEVENT;
+
+#endif
+
+BOOL
+WINAPI
+_TrackMouseEvent(
+ LPTRACKMOUSEEVENT lpEventTrack);
+
+/* Flat Scrollbar control */
+
+#define FLATSB_CLASS16 "flatsb_class"
+#define FLATSB_CLASSA "flatsb_class32"
+#if defined(__GNUC__)
+# define FLATSB_CLASSW (const WCHAR []){ 'f','l','a','t','s','b','_', \
+ 'c','l','a','s','s','3','2',0 }
+#elif defined(_MSC_VER)
+# define FLATSB_CLASSW L"flatsb_class32"
+#else
+static const WCHAR FLATSB_CLASSW[] = { 'f','l','a','t','s','b','_',
+ 'c','l','a','s','s','3','2',0 };
+#endif
+#define FLATSB_CLASS WINELIB_NAME_AW(FLATSB_CLASS)
+
+#define WSB_PROP_CYVSCROLL 0x00000001L
+#define WSB_PROP_CXHSCROLL 0x00000002L
+#define WSB_PROP_CYHSCROLL 0x00000004L
+#define WSB_PROP_CXVSCROLL 0x00000008L
+#define WSB_PROP_CXHTHUMB 0x00000010L
+#define WSB_PROP_CYVTHUMB 0x00000020L
+#define WSB_PROP_VBKGCOLOR 0x00000040L
+#define WSB_PROP_HBKGCOLOR 0x00000080L
+#define WSB_PROP_VSTYLE 0x00000100L
+#define WSB_PROP_HSTYLE 0x00000200L
+#define WSB_PROP_WINSTYLE 0x00000400L
+#define WSB_PROP_PALETTE 0x00000800L
+#define WSB_PROP_MASK 0x00000FFFL
+
+#define FSB_REGULAR_MODE 0
+#define FSB_ENCARTA_MODE 1
+#define FSB_FLAT_MODE 2
+
+
+BOOL WINAPI FlatSB_EnableScrollBar(HWND, INT, UINT);
+BOOL WINAPI FlatSB_ShowScrollBar(HWND, INT, BOOL);
+BOOL WINAPI FlatSB_GetScrollRange(HWND, INT, LPINT, LPINT);
+BOOL WINAPI FlatSB_GetScrollInfo(HWND, INT, LPSCROLLINFO);
+INT WINAPI FlatSB_GetScrollPos(HWND, INT);
+BOOL WINAPI FlatSB_GetScrollProp(HWND, INT, LPINT);
+INT WINAPI FlatSB_SetScrollPos(HWND, INT, INT, BOOL);
+INT WINAPI FlatSB_SetScrollInfo(HWND, INT, LPSCROLLINFO, BOOL);
+INT WINAPI FlatSB_SetScrollRange(HWND, INT, INT, INT, BOOL);
+BOOL WINAPI FlatSB_SetScrollProp(HWND, UINT, INT, BOOL);
+BOOL WINAPI InitializeFlatSB(HWND);
+HRESULT WINAPI UninitializeFlatSB(HWND);
+
+/* Subclassing stuff */
+typedef LRESULT (CALLBACK *SUBCLASSPROC)(HWND, UINT, WPARAM, LPARAM, UINT_PTR, DWORD_PTR);
+BOOL WINAPI SetWindowSubclass(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
+BOOL WINAPI GetWindowSubclass(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR*);
+BOOL WINAPI RemoveWindowSubclass(HWND, SUBCLASSPROC, UINT_PTR);
+LRESULT WINAPI DefSubclassProc(HWND, UINT, WPARAM, LPARAM);
+
+/* Header control */
+
+#define WC_HEADER16 "SysHeader"
+#define WC_HEADERA "SysHeader32"
+#if defined(__GNUC__)
+# define WC_HEADERW (const WCHAR []){ 'S','y','s','H','e','a','d','e','r','3','2',0 }
+#elif defined(_MSC_VER)
+# define WC_HEADERW L"SysHeader32"
+#else
+static const WCHAR WC_HEADERW[] = { 'S','y','s','H','e','a','d','e','r','3','2',0 };
+#endif
+#define WC_HEADER WINELIB_NAME_AW(WC_HEADER)
+
+#define HDS_HORZ 0x0000
+#define HDS_BUTTONS 0x0002
+#define HDS_HOTTRACK 0x0004
+#define HDS_HIDDEN 0x0008
+#define HDS_DRAGDROP 0x0040
+#define HDS_FULLDRAG 0x0080
+
+#define HDI_WIDTH 0x0001
+#define HDI_HEIGHT HDI_WIDTH
+#define HDI_TEXT 0x0002
+#define HDI_FORMAT 0x0004
+#define HDI_LPARAM 0x0008
+#define HDI_BITMAP 0x0010
+#define HDI_IMAGE 0x0020
+#define HDI_DI_SETITEM 0x0040
+#define HDI_ORDER 0x0080
+
+#define HDF_LEFT 0x0000
+#define HDF_RIGHT 0x0001
+#define HDF_CENTER 0x0002
+#define HDF_JUSTIFYMASK 0x0003
+#define HDF_RTLREADING 0x0004
+
+#define HDF_IMAGE 0x0800
+#define HDF_BITMAP_ON_RIGHT 0x1000
+#define HDF_BITMAP 0x2000
+#define HDF_STRING 0x4000
+#define HDF_OWNERDRAW 0x8000
+
+#define HHT_NOWHERE 0x0001
+#define HHT_ONHEADER 0x0002
+#define HHT_ONDIVIDER 0x0004
+#define HHT_ONDIVOPEN 0x0008
+#define HHT_ABOVE 0x0100
+#define HHT_BELOW 0x0200
+#define HHT_TORIGHT 0x0400
+#define HHT_TOLEFT 0x0800
+
+#define HDM_FIRST 0x1200
+#define HDM_GETITEMCOUNT (HDM_FIRST+0)
+#define HDM_INSERTITEMA (HDM_FIRST+1)
+#define HDM_INSERTITEMW (HDM_FIRST+10)
+#define HDM_INSERTITEM WINELIB_NAME_AW(HDM_INSERTITEM)
+#define HDM_DELETEITEM (HDM_FIRST+2)
+#define HDM_GETITEMA (HDM_FIRST+3)
+#define HDM_GETITEMW (HDM_FIRST+11)
+#define HDM_GETITEM WINELIB_NAME_AW(HDM_GETITEM)
+#define HDM_SETITEMA (HDM_FIRST+4)
+#define HDM_SETITEMW (HDM_FIRST+12)
+#define HDM_SETITEM WINELIB_NAME_AW(HDM_SETITEM)
+#define HDM_LAYOUT (HDM_FIRST+5)
+#define HDM_HITTEST (HDM_FIRST+6)
+#define HDM_GETITEMRECT (HDM_FIRST+7)
+#define HDM_SETIMAGELIST (HDM_FIRST+8)
+#define HDM_GETIMAGELIST (HDM_FIRST+9)
+
+#define HDM_ORDERTOINDEX (HDM_FIRST+15)
+#define HDM_CREATEDRAGIMAGE (HDM_FIRST+16)
+#define HDM_GETORDERARRAY (HDM_FIRST+17)
+#define HDM_SETORDERARRAY (HDM_FIRST+18)
+#define HDM_SETHOTDIVIDER (HDM_FIRST+19)
+#define HDM_GETUNICODEFORMAT CCM_GETUNICODEFORMAT
+#define HDM_SETUNICODEFORMAT CCM_SETUNICODEFORMAT
+
+#define HDN_FIRST (0U-300U)
+#define HDN_LAST (0U-399U)
+#define HDN_ITEMCHANGINGA (HDN_FIRST-0)
+#define HDN_ITEMCHANGINGW (HDN_FIRST-20)
+#define HDN_ITEMCHANGING WINELIB_NAME_AW(HDN_ITEMCHANGING)
+#define HDN_ITEMCHANGEDA (HDN_FIRST-1)
+#define HDN_ITEMCHANGEDW (HDN_FIRST-21)
+#define HDN_ITEMCHANGED WINELIB_NAME_AW(HDN_ITEMCHANGED)
+#define HDN_ITEMCLICKA (HDN_FIRST-2)
+#define HDN_ITEMCLICKW (HDN_FIRST-22)
+#define HDN_ITEMCLICK WINELIB_NAME_AW(HDN_ITEMCLICK)
+#define HDN_ITEMDBLCLICKA (HDN_FIRST-3)
+#define HDN_ITEMDBLCLICKW (HDN_FIRST-23)
+#define HDN_ITEMDBLCLICK WINELIB_NAME_AW(HDN_ITEMDBLCLICK)
+#define HDN_DIVIDERDBLCLICKA (HDN_FIRST-5)
+#define HDN_DIVIDERDBLCLICKW (HDN_FIRST-25)
+#define HDN_DIVIDERDBLCLICK WINELIB_NAME_AW(HDN_DIVIDERDBLCLICK)
+#define HDN_BEGINTRACKA (HDN_FIRST-6)
+#define HDN_BEGINTRACKW (HDN_FIRST-26)
+#define HDN_BEGINTRACK WINELIB_NAME_AW(HDN_BEGINTRACK)
+#define HDN_ENDTRACKA (HDN_FIRST-7)
+#define HDN_ENDTRACKW (HDN_FIRST-27)
+#define HDN_ENDTRACK WINELIB_NAME_AW(HDN_ENDTRACK)
+#define HDN_TRACKA (HDN_FIRST-8)
+#define HDN_TRACKW (HDN_FIRST-28)
+#define HDN_TRACK WINELIB_NAME_AW(HDN_TRACK)
+#define HDN_GETDISPINFOA (HDN_FIRST-9)
+#define HDN_GETDISPINFOW (HDN_FIRST-29)
+#define HDN_GETDISPINFO WINELIB_NAME_AW(HDN_GETDISPINFO)
+#define HDN_BEGINDRAG (HDN_FIRST-10)
+#define HDN_ENDDRAG (HDN_FIRST-11)
+
+typedef struct _HD_LAYOUT
+{
+ RECT *prc;
+ WINDOWPOS *pwpos;
+} HDLAYOUT, *LPHDLAYOUT;
+
+#define HD_LAYOUT HDLAYOUT
+
+typedef struct _HD_ITEMA
+{
+ UINT mask;
+ INT cxy;
+ LPSTR pszText;
+ HBITMAP hbm;
+ INT cchTextMax;
+ INT fmt;
+ LPARAM lParam;
+ INT iImage;
+ INT iOrder;
+ UINT type;
+ LPVOID pvFilter;
+} HDITEMA, *LPHDITEMA;
+
+typedef struct _HD_ITEMW
+{
+ UINT mask;
+ INT cxy;
+ LPWSTR pszText;
+ HBITMAP hbm;
+ INT cchTextMax;
+ INT fmt;
+ LPARAM lParam;
+ INT iImage;
+ INT iOrder;
+ UINT type;
+ LPVOID pvFilter;
+} HDITEMW, *LPHDITEMW;
+
+#define HDITEM WINELIB_NAME_AW(HDITEM)
+#define LPHDITEM WINELIB_NAME_AW(LPHDITEM)
+#define HD_ITEM HDITEM
+
+#define HDITEM_V1_SIZEA CCSIZEOF_STRUCT(HDITEMA, lParam)
+#define HDITEM_V1_SIZEW CCSIZEOF_STRUCT(HDITEMW, lParam)
+#define HDITEM_V1_SIZE WINELIB_NAME_AW(HDITEM_V1_SIZE)
+
+typedef struct _HD_HITTESTINFO
+{
+ POINT pt;
+ UINT flags;
+ INT iItem;
+} HDHITTESTINFO, *LPHDHITTESTINFO;
+
+#define HD_HITTESTINFO HDHITTESTINFO
+
+typedef struct tagNMHEADERA
+{
+ NMHDR hdr;
+ INT iItem;
+ INT iButton;
+ HDITEMA *pitem;
+} NMHEADERA, *LPNMHEADERA;
+
+typedef struct tagNMHEADERW
+{
+ NMHDR hdr;
+ INT iItem;
+ INT iButton;
+ HDITEMW *pitem;
+} NMHEADERW, *LPNMHEADERW;
+
+#define NMHEADER WINELIB_NAME_AW(NMHEADER)
+#define LPNMHEADER WINELIB_NAME_AW(LPNMHEADER)
+#define HD_NOTIFY NMHEADER
+
+typedef struct tagNMHDDISPINFOA
+{
+ NMHDR hdr;
+ INT iItem;
+ UINT mask;
+ LPSTR pszText;
+ INT cchTextMax;
+ INT iImage;
+ LPARAM lParam;
+} NMHDDISPINFOA, *LPNMHDDISPINFOA;
+
+typedef struct tagNMHDDISPINFOW
+{
+ NMHDR hdr;
+ INT iItem;
+ UINT mask;
+ LPWSTR pszText;
+ INT cchTextMax;
+ INT iImage;
+ LPARAM lParam;
+} NMHDDISPINFOW, *LPNMHDDISPINFOW;
+
+#define NMHDDISPINFO WINELIB_NAME_AW(NMHDDISPINFO)
+#define LPNMHDDISPINFO WINELIB_NAME_AW(LPNMHDDISPINFO)
+
+#define Header_GetItemCount(hwndHD) \
+ (INT)SNDMSGA((hwndHD),HDM_GETITEMCOUNT,0,0L)
+#define Header_InsertItemA(hwndHD,i,phdi) \
+ (INT)SNDMSGA((hwndHD),HDM_INSERTITEMA,(WPARAM)(INT)(i),(LPARAM)(const HDITEMA*)(phdi))
+#define Header_InsertItemW(hwndHD,i,phdi) \
+ (INT)SNDMSGW((hwndHD),HDM_INSERTITEMW,(WPARAM)(INT)(i),(LPARAM)(const HDITEMW*)(phdi))
+#define Header_InsertItem WINELIB_NAME_AW(Header_InsertItem)
+#define Header_DeleteItem(hwndHD,i) \
+ (BOOL)SNDMSGA((hwndHD),HDM_DELETEITEM,(WPARAM)(INT)(i),0L)
+#define Header_GetItemA(hwndHD,i,phdi) \
+ (BOOL)SNDMSGA((hwndHD),HDM_GETITEMA,(WPARAM)(INT)(i),(LPARAM)(HDITEMA*)(phdi))
+#define Header_GetItemW(hwndHD,i,phdi) \
+ (BOOL)SNDMSGW((hwndHD),HDM_GETITEMW,(WPARAM)(INT)(i),(LPARAM)(HDITEMW*)(phdi))
+#define Header_GetItem WINELIB_NAME_AW(Header_GetItem)
+#define Header_SetItemA(hwndHD,i,phdi) \
+ (BOOL)SNDMSGA((hwndHD),HDM_SETITEMA,(WPARAM)(INT)(i),(LPARAM)(const HDITEMA*)(phdi))
+#define Header_SetItemW(hwndHD,i,phdi) \
+ (BOOL)SNDMSGW((hwndHD),HDM_SETITEMW,(WPARAM)(INT)(i),(LPARAM)(const HDITEMW*)(phdi))
+#define Header_SetItem WINELIB_NAME_AW(Header_SetItem)
+#define Header_Layout(hwndHD,playout) \
+ (BOOL)SNDMSGA((hwndHD),HDM_LAYOUT,0,(LPARAM)(LPHDLAYOUT)(playout))
+#define Header_GetItemRect(hwnd,iItem,lprc) \
+ (BOOL)SNDMSGA((hwnd),HDM_GETITEMRECT,(WPARAM)iItem,(LPARAM)lprc)
+#define Header_SetImageList(hwnd,himl) \
+ (HIMAGELIST)SNDMSGA((hwnd),HDM_SETIMAGELIST,0,(LPARAM)himl)
+#define Header_GetImageList(hwnd) \
+ (HIMAGELIST)SNDMSGA((hwnd),HDM_GETIMAGELIST,0,0)
+#define Header_OrderToIndex(hwnd,i) \
+ (INT)SNDMSGA((hwnd),HDM_ORDERTOINDEX,(WPARAM)i,0)
+#define Header_CreateDragImage(hwnd,i) \
+ (HIMAGELIST)SNDMSGA((hwnd),HDM_CREATEDRAGIMAGE,(WPARAM)i,0)
+#define Header_GetOrderArray(hwnd,iCount,lpi) \
+ (BOOL)SNDMSGA((hwnd),HDM_GETORDERARRAY,(WPARAM)iCount,(LPARAM)lpi)
+#define Header_SetOrderArray(hwnd,iCount,lpi) \
+ (BOOL)SNDMSGA((hwnd),HDM_SETORDERARRAY,(WPARAM)iCount,(LPARAM)lpi)
+#define Header_SetHotDivider(hwnd,fPos,dw) \
+ (INT)SNDMSGA((hwnd),HDM_SETHOTDIVIDER,(WPARAM)fPos,(LPARAM)dw)
+#define Header_SetUnicodeFormat(hwnd,fUnicode) \
+ (BOOL)SNDMSGA((hwnd),HDM_SETUNICODEFORMAT,(WPARAM)(fUnicode),0)
+#define Header_GetUnicodeFormat(hwnd) \
+ (BOOL)SNDMSGA((hwnd),HDM_GETUNICODEFORMAT,0,0)
+
+
+/* Toolbar */
+
+#define TOOLBARCLASSNAME16 "ToolbarWindow"
+#define TOOLBARCLASSNAMEA "ToolbarWindow32"
+#if defined(__GNUC__)
+# define TOOLBARCLASSNAMEW (const WCHAR []){ 'T','o','o','l','b','a','r', \
+ 'W','i','n','d','o','w','3','2',0 }
+#elif defined(_MSC_VER)
+# define TOOLBARCLASSNAMEW L"ToolbarWindow32"
+#else
+static const WCHAR TOOLBARCLASSNAMEW[] = { 'T','o','o','l','b','a','r',
+ 'W','i','n','d','o','w','3','2',0 };
+#endif
+#define TOOLBARCLASSNAME WINELIB_NAME_AW(TOOLBARCLASSNAME)
+
+#define CMB_MASKED 0x02
+
+#define TBSTATE_CHECKED 0x01
+#define TBSTATE_PRESSED 0x02
+#define TBSTATE_ENABLED 0x04
+#define TBSTATE_HIDDEN 0x08
+#define TBSTATE_INDETERMINATE 0x10
+#define TBSTATE_WRAP 0x20
+#define TBSTATE_ELLIPSES 0x40
+#define TBSTATE_MARKED 0x80
+
+
+/* as of _WIN32_IE >= 0x0500 the following symbols are obsolete,
+ * "everyone" should use the BTNS_... stuff below
+ */
+#define TBSTYLE_BUTTON 0x00
+#define TBSTYLE_SEP 0x01
+#define TBSTYLE_CHECK 0x02
+#define TBSTYLE_GROUP 0x04
+#define TBSTYLE_CHECKGROUP (TBSTYLE_GROUP | TBSTYLE_CHECK)
+#define TBSTYLE_DROPDOWN 0x08
+#define TBSTYLE_AUTOSIZE 0x10
+#define TBSTYLE_NOPREFIX 0x20
+#define BTNS_BUTTON TBSTYLE_BUTTON
+#define BTNS_SEP TBSTYLE_SEP
+#define BTNS_CHECK TBSTYLE_CHECK
+#define BTNS_GROUP TBSTYLE_GROUP
+#define BTNS_CHECKGROUP TBSTYLE_CHECKGROUP
+#define BTNS_DROPDOWN TBSTYLE_DROPDOWN
+#define BTNS_AUTOSIZE TBSTYLE_AUTOSIZE
+#define BTNS_NOPREFIX TBSTYLE_NOPREFIX
+#define BTNS_SHOWTEXT 0x40 /* ignored unless TBSTYLE_EX_MIXEDB set */
+#define BTNS_WHOLEDROPDOWN 0x80 /* draw dropdown arrow, but without split arrow section */
+
+#define TBSTYLE_TOOLTIPS 0x0100
+#define TBSTYLE_WRAPABLE 0x0200
+#define TBSTYLE_ALTDRAG 0x0400
+#define TBSTYLE_FLAT 0x0800
+#define TBSTYLE_LIST 0x1000
+#define TBSTYLE_CUSTOMERASE 0x2000
+#define TBSTYLE_REGISTERDROP 0x4000
+#define TBSTYLE_TRANSPARENT 0x8000
+#define TBSTYLE_EX_DRAWDDARROWS 0x00000001
+#define TBSTYLE_EX_UNDOC1 0x00000004 /* similar to TBSTYLE_WRAPABLE */
+#define TBSTYLE_EX_MIXEDBUTTONS 0x00000008
+#define TBSTYLE_EX_HIDECLIPPEDBUTTONS 0x00000010 /* don't show partially obscured buttons */
+#define TBSTYLE_EX_DOUBLEBUFFER 0x00000080 /* Double Buffer the toolbar ??? */
+
+#define TBIF_IMAGE 0x00000001
+#define TBIF_TEXT 0x00000002
+#define TBIF_STATE 0x00000004
+#define TBIF_STYLE 0x00000008
+#define TBIF_LPARAM 0x00000010
+#define TBIF_COMMAND 0x00000020
+#define TBIF_SIZE 0x00000040
+
+#define TBBF_LARGE 0x0001
+
+#define TB_ENABLEBUTTON (WM_USER+1)
+#define TB_CHECKBUTTON (WM_USER+2)
+#define TB_PRESSBUTTON (WM_USER+3)
+#define TB_HIDEBUTTON (WM_USER+4)
+#define TB_INDETERMINATE (WM_USER+5)
+#define TB_MARKBUTTON (WM_USER+6)
+#define TB_ISBUTTONENABLED (WM_USER+9)
+#define TB_ISBUTTONCHECKED (WM_USER+10)
+#define TB_ISBUTTONPRESSED (WM_USER+11)
+#define TB_ISBUTTONHIDDEN (WM_USER+12)
+#define TB_ISBUTTONINDETERMINATE (WM_USER+13)
+#define TB_ISBUTTONHIGHLIGHTED (WM_USER+14)
+#define TB_SETSTATE (WM_USER+17)
+#define TB_GETSTATE (WM_USER+18)
+#define TB_ADDBITMAP (WM_USER+19)
+#define TB_ADDBUTTONSA (WM_USER+20)
+#define TB_ADDBUTTONSW (WM_USER+68)
+#define TB_ADDBUTTONS WINELIB_NAME_AW(TB_ADDBUTTONS)
+#define TB_HITTEST (WM_USER+69)
+#define TB_INSERTBUTTONA (WM_USER+21)
+#define TB_INSERTBUTTONW (WM_USER+67)
+#define TB_INSERTBUTTON WINELIB_NAME_AW(TB_INSERTBUTTON)
+#define TB_DELETEBUTTON (WM_USER+22)
+#define TB_GETBUTTON (WM_USER+23)
+#define TB_BUTTONCOUNT (WM_USER+24)
+#define TB_COMMANDTOINDEX (WM_USER+25)
+#define TB_SAVERESTOREA (WM_USER+26)
+#define TB_SAVERESTOREW (WM_USER+76)
+#define TB_SAVERESTORE WINELIB_NAME_AW(TB_SAVERESTORE)
+#define TB_CUSTOMIZE (WM_USER+27)
+#define TB_ADDSTRINGA (WM_USER+28)
+#define TB_ADDSTRINGW (WM_USER+77)
+#define TB_ADDSTRING WINELIB_NAME_AW(TB_ADDSTRING)
+#define TB_GETITEMRECT (WM_USER+29)
+#define TB_BUTTONSTRUCTSIZE (WM_USER+30)
+#define TB_SETBUTTONSIZE (WM_USER+31)
+#define TB_SETBITMAPSIZE (WM_USER+32)
+#define TB_AUTOSIZE (WM_USER+33)
+#define TB_GETTOOLTIPS (WM_USER+35)
+#define TB_SETTOOLTIPS (WM_USER+36)
+#define TB_SETPARENT (WM_USER+37)
+#define TB_SETROWS (WM_USER+39)
+#define TB_GETROWS (WM_USER+40)
+#define TB_GETBITMAPFLAGS (WM_USER+41)
+#define TB_SETCMDID (WM_USER+42)
+#define TB_CHANGEBITMAP (WM_USER+43)
+#define TB_GETBITMAP (WM_USER+44)
+#define TB_GETBUTTONTEXTA (WM_USER+45)
+#define TB_GETBUTTONTEXTW (WM_USER+75)
+#define TB_GETBUTTONTEXT WINELIB_NAME_AW(TB_GETBUTTONTEXT)
+#define TB_REPLACEBITMAP (WM_USER+46)
+#define TB_SETINDENT (WM_USER+47)
+#define TB_SETIMAGELIST (WM_USER+48)
+#define TB_GETIMAGELIST (WM_USER+49)
+#define TB_LOADIMAGES (WM_USER+50)
+#define TB_GETRECT (WM_USER+51) /* wParam is the Cmd instead of index */
+#define TB_SETHOTIMAGELIST (WM_USER+52)
+#define TB_GETHOTIMAGELIST (WM_USER+53)
+#define TB_SETDISABLEDIMAGELIST (WM_USER+54)
+#define TB_GETDISABLEDIMAGELIST (WM_USER+55)
+#define TB_SETSTYLE (WM_USER+56)
+#define TB_GETSTYLE (WM_USER+57)
+#define TB_GETBUTTONSIZE (WM_USER+58)
+#define TB_SETBUTTONWIDTH (WM_USER+59)
+#define TB_SETMAXTEXTROWS (WM_USER+60)
+#define TB_GETTEXTROWS (WM_USER+61)
+#define TB_GETOBJECT (WM_USER+62)
+#define TB_GETBUTTONINFOW (WM_USER+63)
+#define TB_GETBUTTONINFOA (WM_USER+65)
+#define TB_GETBUTTONINFO WINELIB_NAME_AW(TB_GETBUTTONINFO)
+#define TB_SETBUTTONINFOW (WM_USER+64)
+#define TB_SETBUTTONINFOA (WM_USER+66)
+#define TB_SETBUTTONINFO WINELIB_NAME_AW(TB_SETBUTTONINFO)
+#define TB_SETDRAWTEXTFLAGS (WM_USER+70)
+#define TB_GETHOTITEM (WM_USER+71)
+#define TB_SETHOTITEM (WM_USER+72)
+#define TB_SETANCHORHIGHLIGHT (WM_USER+73)
+#define TB_GETANCHORHIGHLIGHT (WM_USER+74)
+#define TB_MAPACCELERATORA (WM_USER+78)
+#define TB_MAPACCELERATORW (WM_USER+90)
+#define TB_MAPACCELERATOR WINELIB_NAME_AW(TB_MAPACCELERATOR)
+#define TB_GETINSERTMARK (WM_USER+79)
+#define TB_SETINSERTMARK (WM_USER+80)
+#define TB_INSERTMARKHITTEST (WM_USER+81)
+#define TB_MOVEBUTTON (WM_USER+82)
+#define TB_GETMAXSIZE (WM_USER+83)
+#define TB_SETEXTENDEDSTYLE (WM_USER+84)
+#define TB_GETEXTENDEDSTYLE (WM_USER+85)
+#define TB_GETPADDING (WM_USER+86)
+#define TB_SETPADDING (WM_USER+87)
+#define TB_SETINSERTMARKCOLOR (WM_USER+88)
+#define TB_GETINSERTMARKCOLOR (WM_USER+89)
+#define TB_SETCOLORSCHEME CCM_SETCOLORSCHEME
+#define TB_GETCOLORSCHEME CCM_GETCOLORSCHEME
+#define TB_SETUNICODEFORMAT CCM_SETUNICODEFORMAT
+#define TB_GETUNICODEFORMAT CCM_GETUNICODEFORMAT
+#define TB_GETSTRINGW (WM_USER+91)
+#define TB_GETSTRINGA (WM_USER+92)
+#define TB_GETSTRING WINELIB_NAME_AW(TB_GETSTRING)
+
+/* undocumented messages in Toolbar */
+#define TB_UNKWN45D (WM_USER+93)
+#define TB_UNKWN45E (WM_USER+94)
+#define TB_UNKWN460 (WM_USER+96)
+#define TB_UNKWN463 (WM_USER+99)
+#define TB_UNKWN464 (WM_USER+100)
+
+
+#define TBN_FIRST (0U-700U)
+#define TBN_LAST (0U-720U)
+#define TBN_GETBUTTONINFOA (TBN_FIRST-0)
+#define TBN_GETBUTTONINFOW (TBN_FIRST-20)
+#define TBN_GETBUTTONINFO WINELIB_NAME_AW(TBN_GETBUTTONINFO)
+#define TBN_BEGINDRAG (TBN_FIRST-1)
+#define TBN_ENDDRAG (TBN_FIRST-2)
+#define TBN_BEGINADJUST (TBN_FIRST-3)
+#define TBN_ENDADJUST (TBN_FIRST-4)
+#define TBN_RESET (TBN_FIRST-5)
+#define TBN_QUERYINSERT (TBN_FIRST-6)
+#define TBN_QUERYDELETE (TBN_FIRST-7)
+#define TBN_TOOLBARCHANGE (TBN_FIRST-8)
+#define TBN_CUSTHELP (TBN_FIRST-9)
+#define TBN_DROPDOWN (TBN_FIRST-10)
+#define TBN_GETOBJECT (TBN_FIRST-12)
+#define TBN_HOTITEMCHANGE (TBN_FIRST-13)
+#define TBN_DRAGOUT (TBN_FIRST-14)
+#define TBN_DELETINGBUTTON (TBN_FIRST-15)
+#define TBN_GETDISPINFOA (TBN_FIRST-16)
+#define TBN_GETDISPINFOW (TBN_FIRST-17)
+#define TBN_GETDISPINFO WINELIB_NAME_AW(TBN_GETDISPINFO)
+#define TBN_GETINFOTIPA (TBN_FIRST-18)
+#define TBN_GETINFOTIPW (TBN_FIRST-19)
+#define TBN_GETINFOTIP WINELIB_NAME_AW(TBN_GETINFOTIP)
+#define TBN_INITCUSTOMIZE (TBN_FIRST-23)
+#define TBNRF_HIDEHELP 0x00000001
+
+
+/* Return values from TBN_DROPDOWN */
+#define TBDDRET_DEFAULT 0
+#define TBDDRET_NODEFAULT 1
+#define TBDDRET_TREATPRESSED 2
+
+typedef struct _NMTBCUSTOMDRAW
+{
+ NMCUSTOMDRAW nmcd;
+ HBRUSH hbrMonoDither;
+ HBRUSH hbrLines;
+ HPEN hpenLines;
+ COLORREF clrText;
+ COLORREF clrMark;
+ COLORREF clrTextHighlight;
+ COLORREF clrBtnFace;
+ COLORREF clrBtnHighlight;
+ COLORREF clrHighlightHotTrack;
+ RECT rcText;
+ int nStringBkMode;
+ int nHLStringBkMode;
+} NMTBCUSTOMDRAW, *LPNMTBCUSTOMDRAW;
+
+/* return flags for Toolbar NM_CUSTOMDRAW notifications */
+#define TBCDRF_NOEDGES 0x00010000 /* Don't draw button edges */
+#define TBCDRF_HILITEHOTTRACK 0x00020000 /* Use color of the button bkgnd */
+ /* when hottracked */
+#define TBCDRF_NOOFFSET 0x00040000 /* No offset button if pressed */
+#define TBCDRF_NOMARK 0x00080000 /* Don't draw default highlight */
+ /* for TBSTATE_MARKED */
+#define TBCDRF_NOETCHEDEFFECT 0x00100000 /* No etched effect for */
+ /* disabled items */
+#define TBCDRF_BLENDICON 0x00200000 /* ILD_BLEND50 on the icon image */
+#define TBCDRF_NOBACKGROUND 0x00400000 /* ILD_BLEND50 on the icon image */
+
+
+/* This is just for old CreateToolbar. */
+/* Don't use it in new programs. */
+typedef struct _OLDTBBUTTON {
+ INT iBitmap;
+ INT idCommand;
+ BYTE fsState;
+ BYTE fsStyle;
+ BYTE bReserved[2];
+ DWORD dwData;
+} OLDTBBUTTON, *POLDTBBUTTON, *LPOLDTBBUTTON;
+typedef const OLDTBBUTTON *LPCOLDTBBUTTON;
+
+
+typedef struct _TBBUTTON {
+ INT iBitmap;
+ INT idCommand;
+ BYTE fsState;
+ BYTE fsStyle;
+ BYTE bReserved[2];
+ DWORD dwData;
+ INT iString;
+} TBBUTTON, *PTBBUTTON, *LPTBBUTTON;
+typedef const TBBUTTON *LPCTBBUTTON;
+
+
+typedef struct _COLORMAP {
+ COLORREF from;
+ COLORREF to;
+} COLORMAP, *LPCOLORMAP;
+
+
+typedef struct tagTBADDBITMAP {
+ HINSTANCE hInst;
+ UINT nID;
+} TBADDBITMAP, *LPTBADDBITMAP;
+
+#define HINST_COMMCTRL ((HINSTANCE)-1)
+#define IDB_STD_SMALL_COLOR 0
+#define IDB_STD_LARGE_COLOR 1
+#define IDB_VIEW_SMALL_COLOR 4
+#define IDB_VIEW_LARGE_COLOR 5
+#define IDB_HIST_SMALL_COLOR 8
+#define IDB_HIST_LARGE_COLOR 9
+
+#define STD_CUT 0
+#define STD_COPY 1
+#define STD_PASTE 2
+#define STD_UNDO 3
+#define STD_REDOW 4
+#define STD_DELETE 5
+#define STD_FILENEW 6
+#define STD_FILEOPEN 7
+#define STD_FILESAVE 8
+#define STD_PRINTPRE 9
+#define STD_PROPERTIES 10
+#define STD_HELP 11
+#define STD_FIND 12
+#define STD_REPLACE 13
+#define STD_PRINT 14
+
+#define VIEW_LARGEICONS 0
+#define VIEW_SMALLICONS 1
+#define VIEW_LIST 2
+#define VIEW_DETAILS 3
+#define VIEW_SORTNAME 4
+#define VIEW_SORTSIZE 5
+#define VIEW_SORTDATE 6
+#define VIEW_SORTTYPE 7
+#define VIEW_PARENTFOLDER 8
+#define VIEW_NETCONNECT 9
+#define VIEW_NETDISCONNECT 10
+#define VIEW_NEWFOLDER 11
+#define VIEW_VIEWMENU 12
+
+#define HIST_BACK 0
+#define HIST_FORWARD 1
+#define HIST_FAVORITES 2
+#define HIST_ADDTOFAVORITES 3
+#define HIST_VIEWTREE 4
+
+typedef struct tagTBSAVEPARAMSA {
+ HKEY hkr;
+ LPCSTR pszSubKey;
+ LPCSTR pszValueName;
+} TBSAVEPARAMSA, *LPTBSAVEPARAMSA;
+
+typedef struct tagTBSAVEPARAMSW {
+ HKEY hkr;
+ LPCWSTR pszSubKey;
+ LPCWSTR pszValueName;
+} TBSAVEPARAMSW, *LPTBSAVEPARAMSW;
+
+#define TBSAVEPARAMS WINELIB_NAME_AW(TBSAVEPARAMS)
+#define LPTBSAVEPARAMS WINELIB_NAME_AW(LPTBSAVEPARAMS)
+
+typedef struct
+{
+ UINT cbSize;
+ DWORD dwMask;
+ INT idCommand;
+ INT iImage;
+ BYTE fsState;
+ BYTE fsStyle;
+ WORD cx;
+ DWORD lParam;
+ LPSTR pszText;
+ INT cchText;
+} TBBUTTONINFOA, *LPTBBUTTONINFOA;
+
+typedef struct
+{
+ UINT cbSize;
+ DWORD dwMask;
+ INT idCommand;
+ INT iImage;
+ BYTE fsState;
+ BYTE fsStyle;
+ WORD cx;
+ DWORD lParam;
+ LPWSTR pszText;
+ INT cchText;
+} TBBUTTONINFOW, *LPTBBUTTONINFOW;
+
+#define TBBUTTONINFO WINELIB_NAME_AW(TBBUTTONINFO)
+#define LPTBBUTTONINFO WINELIB_NAME_AW(LPTBBUTTONINFO)
+
+typedef struct tagNMTBHOTITEM
+{
+ NMHDR hdr;
+ int idOld;
+ int idNew;
+ DWORD dwFlags;
+} NMTBHOTITEM, *LPNMTBHOTITEM;
+
+typedef struct tagNMTBGETINFOTIPA
+{
+ NMHDR hdr;
+ LPSTR pszText;
+ INT cchTextMax;
+ INT iItem;
+ LPARAM lParam;
+} NMTBGETINFOTIPA, *LPNMTBGETINFOTIPA;
+
+typedef struct tagNMTBGETINFOTIPW
+{
+ NMHDR hdr;
+ LPWSTR pszText;
+ INT cchTextMax;
+ INT iItem;
+ LPARAM lParam;
+} NMTBGETINFOTIPW, *LPNMTBGETINFOTIPW;
+
+#define NMTBGETINFOTIP WINELIB_NAME_AW(NMTBGETINFOFTIP)
+#define LPNMTBGETINFOTIP WINELIB_NAME_AW(LPNMTBGETINFOTIP)
+
+typedef struct
+{
+ NMHDR hdr;
+ DWORD dwMask;
+ int idCommand;
+ DWORD lParam;
+ int iImage;
+ LPSTR pszText;
+ int cchText;
+} NMTBDISPINFOA, *LPNMTBDISPINFOA;
+
+typedef struct
+{
+ NMHDR hdr;
+ DWORD dwMask;
+ int idCommand;
+ DWORD lParam;
+ int iImage;
+ LPWSTR pszText;
+ int cchText;
+} NMTBDISPINFOW, *LPNMTBDISPINFOW;
+
+#define NMTBDISPINFO WINELIB_NAME_AW(NMTBDISPINFO)
+#define LPNMTBDISPINFO WINELIB_NAME_AW(LPNMTBDISPINFO)
+
+/* contents of dwMask in the NMTBDISPINFO structure */
+#define TBNF_IMAGE 0x00000001
+#define TBNF_TEXT 0x00000002
+#define TBNF_DI_SETITEM 0x10000000
+
+
+typedef struct tagNMTOOLBARA
+{
+ NMHDR hdr;
+ INT iItem;
+ TBBUTTON tbButton;
+ INT cchText;
+ LPSTR pszText;
+ RECT rcButton; /* Version 5.80 */
+} NMTOOLBARA, *LPNMTOOLBARA, TBNOTIFYA, *LPTBNOTIFYA;
+
+typedef struct tagNMTOOLBARW
+{
+ NMHDR hdr;
+ INT iItem;
+ TBBUTTON tbButton;
+ INT cchText;
+ LPWSTR pszText;
+ RECT rcButton; /* Version 5.80 */
+} NMTOOLBARW, *LPNMTOOLBARW, TBNOTIFYW, *LPTBNOTIFYW;
+
+#define NMTOOLBAR WINELIB_NAME_AW(NMTOOLBAR)
+#define LPNMTOOLBAR WINELIB_NAME_AW(LPNMTOOLBAR)
+#define TBNOTIFY WINELIB_NAME_AW(TBNOTIFY)
+#define LPTBNOTIFY WINELIB_NAME_AW(LPTBNOTIFY)
+
+typedef struct
+{
+ HINSTANCE hInstOld;
+ UINT nIDOld;
+ HINSTANCE hInstNew;
+ UINT nIDNew;
+ INT nButtons;
+} TBREPLACEBITMAP, *LPTBREPLACEBITMAP;
+
+#define HICF_OTHER 0x00000000
+#define HICF_MOUSE 0x00000001 /* Triggered by mouse */
+#define HICF_ARROWKEYS 0x00000002 /* Triggered by arrow keys */
+#define HICF_ACCELERATOR 0x00000004 /* Triggered by accelerator */
+#define HICF_DUPACCEL 0x00000008 /* This accelerator is not unique */
+#define HICF_ENTERING 0x00000010 /* idOld is invalid */
+#define HICF_LEAVING 0x00000020 /* idNew is invalid */
+#define HICF_RESELECT 0x00000040 /* hot item reselected */
+#define HICF_LMOUSE 0x00000080 /* left mouse button selected */
+#define HICF_TOGGLEDROPDOWN 0x00000100 /* Toggle button's dropdown state */
+
+typedef struct
+{
+ int iButton;
+ DWORD dwFlags;
+} TBINSERTMARK, *LPTBINSERTMARK;
+#define TBIMHT_AFTER 0x00000001 /* TRUE = insert After iButton, otherwise before */
+#define TBIMHT_BACKGROUND 0x00000002 /* TRUE if and only if missed buttons completely */
+
+HWND WINAPI
+CreateToolbar(HWND, DWORD, UINT, INT, HINSTANCE,
+ UINT, LPCOLDTBBUTTON, INT);
+
+HWND WINAPI
+CreateToolbarEx(HWND, DWORD, UINT, INT,
+ HINSTANCE, UINT, LPCTBBUTTON,
+ INT, INT, INT, INT, INT, UINT);
+
+HBITMAP WINAPI
+CreateMappedBitmap (HINSTANCE, INT, UINT, LPCOLORMAP, INT);
+
+
+/* Tool tips */
+
+#define TOOLTIPS_CLASS16 "tooltips_class"
+#define TOOLTIPS_CLASSA "tooltips_class32"
+#if defined(__GNUC__)
+# define TOOLTIPS_CLASSW (const WCHAR []){ 't','o','o','l','t','i','p','s','_', \
+ 'c','l','a','s','s','3','2',0 }
+#elif defined(_MSC_VER)
+# define TOOLTIPS_CLASSW L"tooltips_class32"
+#else
+static const WCHAR TOOLTIPS_CLASSW[] = { 't','o','o','l','t','i','p','s','_',
+ 'c','l','a','s','s','3','2',0 };
+#endif
+#define TOOLTIPS_CLASS WINELIB_NAME_AW(TOOLTIPS_CLASS)
+
+#define INFOTIPSIZE 1024
+
+#define TTS_ALWAYSTIP 0x01
+#define TTS_NOPREFIX 0x02
+
+#define TTF_IDISHWND 0x0001
+#define TTF_CENTERTIP 0x0002
+#define TTF_RTLREADING 0x0004
+#define TTF_SUBCLASS 0x0010
+#define TTF_TRACK 0x0020
+#define TTF_ABSOLUTE 0x0080
+#define TTF_TRANSPARENT 0x0100
+#define TTF_DI_SETITEM 0x8000 /* valid only on the TTN_NEEDTEXT callback */
+
+
+#define TTDT_AUTOMATIC 0
+#define TTDT_RESHOW 1
+#define TTDT_AUTOPOP 2
+#define TTDT_INITIAL 3
+
+
+#define TTM_ACTIVATE (WM_USER+1)
+#define TTM_SETDELAYTIME (WM_USER+3)
+#define TTM_ADDTOOLA (WM_USER+4)
+#define TTM_ADDTOOLW (WM_USER+50)
+#define TTM_ADDTOOL WINELIB_NAME_AW(TTM_ADDTOOL)
+#define TTM_DELTOOLA (WM_USER+5)
+#define TTM_DELTOOLW (WM_USER+51)
+#define TTM_DELTOOL WINELIB_NAME_AW(TTM_DELTOOL)
+#define TTM_NEWTOOLRECTA (WM_USER+6)
+#define TTM_NEWTOOLRECTW (WM_USER+52)
+#define TTM_NEWTOOLRECT WINELIB_NAME_AW(TTM_NEWTOOLRECT)
+#define TTM_RELAYEVENT (WM_USER+7)
+#define TTM_GETTOOLINFOA (WM_USER+8)
+#define TTM_GETTOOLINFOW (WM_USER+53)
+#define TTM_GETTOOLINFO WINELIB_NAME_AW(TTM_GETTOOLINFO)
+#define TTM_SETTOOLINFOA (WM_USER+9)
+#define TTM_SETTOOLINFOW (WM_USER+54)
+#define TTM_SETTOOLINFO WINELIB_NAME_AW(TTM_SETTOOLINFO)
+#define TTM_HITTESTA (WM_USER+10)
+#define TTM_HITTESTW (WM_USER+55)
+#define TTM_HITTEST WINELIB_NAME_AW(TTM_HITTEST)
+#define TTM_GETTEXTA (WM_USER+11)
+#define TTM_GETTEXTW (WM_USER+56)
+#define TTM_GETTEXT WINELIB_NAME_AW(TTM_GETTEXT)
+#define TTM_UPDATETIPTEXTA (WM_USER+12)
+#define TTM_UPDATETIPTEXTW (WM_USER+57)
+#define TTM_UPDATETIPTEXT WINELIB_NAME_AW(TTM_UPDATETIPTEXT)
+#define TTM_GETTOOLCOUNT (WM_USER+13)
+#define TTM_ENUMTOOLSA (WM_USER+14)
+#define TTM_ENUMTOOLSW (WM_USER+58)
+#define TTM_ENUMTOOLS WINELIB_NAME_AW(TTM_ENUMTOOLS)
+#define TTM_GETCURRENTTOOLA (WM_USER+15)
+#define TTM_GETCURRENTTOOLW (WM_USER+59)
+#define TTM_GETCURRENTTOOL WINELIB_NAME_AW(TTM_GETCURRENTTOOL)
+#define TTM_WINDOWFROMPOINT (WM_USER+16)
+#define TTM_TRACKACTIVATE (WM_USER+17)
+#define TTM_TRACKPOSITION (WM_USER+18)
+#define TTM_SETTIPBKCOLOR (WM_USER+19)
+#define TTM_SETTIPTEXTCOLOR (WM_USER+20)
+#define TTM_GETDELAYTIME (WM_USER+21)
+#define TTM_GETTIPBKCOLOR (WM_USER+22)
+#define TTM_GETTIPTEXTCOLOR (WM_USER+23)
+#define TTM_SETMAXTIPWIDTH (WM_USER+24)
+#define TTM_GETMAXTIPWIDTH (WM_USER+25)
+#define TTM_SETMARGIN (WM_USER+26)
+#define TTM_GETMARGIN (WM_USER+27)
+#define TTM_POP (WM_USER+28)
+#define TTM_UPDATE (WM_USER+29)
+#define TTM_GETBUBBLESIZE (WM_USER+30)
+
+
+#define TTN_FIRST (0U-520U)
+#define TTN_LAST (0U-549U)
+#define TTN_GETDISPINFOA (TTN_FIRST-0)
+#define TTN_GETDISPINFOW (TTN_FIRST-10)
+#define TTN_GETDISPINFO WINELIB_NAME_AW(TTN_GETDISPINFO)
+#define TTN_SHOW (TTN_FIRST-1)
+#define TTN_POP (TTN_FIRST-2)
+
+#define TTN_NEEDTEXT TTN_GETDISPINFO
+#define TTN_NEEDTEXTA TTN_GETDISPINFOA
+#define TTN_NEEDTEXTW TTN_GETDISPINFOW
+
+typedef struct tagTOOLINFOA {
+ UINT cbSize;
+ UINT uFlags;
+ HWND hwnd;
+ UINT uId;
+ RECT rect;
+ HINSTANCE hinst;
+ LPSTR lpszText;
+ LPARAM lParam;
+} TTTOOLINFOA, *LPTOOLINFOA, *PTOOLINFOA, *LPTTTOOLINFOA;
+
+typedef struct tagTOOLINFOW {
+ UINT cbSize;
+ UINT uFlags;
+ HWND hwnd;
+ UINT uId;
+ RECT rect;
+ HINSTANCE hinst;
+ LPWSTR lpszText;
+ LPARAM lParam;
+} TTTOOLINFOW, *LPTOOLINFOW, *PTOOLINFOW, *LPTTTOOLINFOW;
+
+#define TTTOOLINFO WINELIB_NAME_AW(TTTOOLINFO)
+#define TOOLINFO WINELIB_NAME_AW(TTTOOLINFO)
+#define PTOOLINFO WINELIB_NAME_AW(PTOOLINFO)
+#define LPTTTOOLINFO WINELIB_NAME_AW(LPTTTOOLINFO)
+#define LPTOOLINFO WINELIB_NAME_AW(LPTOOLINFO)
+
+#define TTTOOLINFO_V1_SIZEA CCSIZEOF_STRUCT(TTTOOLINFOA, lpszText)
+#define TTTOOLINFO_V1_SIZEW CCSIZEOF_STRUCT(TTTOOLINFOW, lpszText)
+#define TTTOOLINFO_V1_SIZE WINELIB_NAME_AW(TTTOOLINFO_V1_SIZE)
+
+typedef struct _TT_HITTESTINFOA
+{
+ HWND hwnd;
+ POINT pt;
+ TTTOOLINFOA ti;
+} TTHITTESTINFOA, *LPTTHITTESTINFOA;
+#define LPHITTESTINFOA LPTTHITTESTINFOA
+
+typedef struct _TT_HITTESTINFOW
+{
+ HWND hwnd;
+ POINT pt;
+ TTTOOLINFOW ti;
+} TTHITTESTINFOW, *LPTTHITTESTINFOW;
+#define LPHITTESTINFOW LPTTHITTESTINFOW
+
+#define TTHITTESTINFO WINELIB_NAME_AW(TTHITTESTINFO)
+#define LPTTHITTESTINFO WINELIB_NAME_AW(LPTTHITTESTINFO)
+#define LPHITTESTINFO WINELIB_NAME_AW(LPHITTESTINFO)
+
+typedef struct tagNMTTDISPINFOA
+{
+ NMHDR hdr;
+ LPSTR lpszText;
+ CHAR szText[80];
+ HINSTANCE hinst;
+ UINT uFlags;
+ LPARAM lParam;
+} NMTTDISPINFOA, *LPNMTTDISPINFOA;
+
+typedef struct tagNMTTDISPINFOW
+{
+ NMHDR hdr;
+ LPWSTR lpszText;
+ WCHAR szText[80];
+ HINSTANCE hinst;
+ UINT uFlags;
+ LPARAM lParam;
+} NMTTDISPINFOW, *LPNMTTDISPINFOW;
+
+#define NMTTDISPINFO WINELIB_NAME_AW(NMTTDISPINFO)
+#define LPNMTTDISPINFO WINELIB_NAME_AW(LPNMTTDISPINFO)
+
+#define NMTTDISPINFO_V1_SIZEA CCSIZEOF_STRUCT(NMTTDISPINFOA, uFlags)
+#define NMTTDISPINFO_V1_SIZEW CCSIZEOF_STRUCT(NMTTDISPINFOW, uFlags)
+#define NMTTDISPINFO_V1_SIZE WINELIB_NAME_AW(NMTTDISPINFO_V1_SIZE)
+
+#define TOOLTIPTEXTW NMTTDISPINFOW
+#define TOOLTIPTEXTA NMTTDISPINFOA
+#define TOOLTIPTEXT NMTTDISPINFO
+#define LPTOOLTIPTEXTW LPNMTTDISPINFOW
+#define LPTOOLTIPTEXTA LPNMTTDISPINFOA
+#define LPTOOLTIPTEXT LPNMTTDISPINFO
+
+
+/* Rebar control */
+
+#define REBARCLASSNAME16 "ReBarWindow"
+#define REBARCLASSNAMEA "ReBarWindow32"
+#if defined(__GNUC__)
+# define REBARCLASSNAMEW (const WCHAR []){ 'R','e','B','a','r', \
+ 'W','i','n','d','o','w','3','2',0 }
+#elif defined(_MSC_VER)
+# define REBARCLASSNAMEW L"ReBarWindow32"
+#else
+static const WCHAR REBARCLASSNAMEW[] = { 'R','e','B','a','r',
+ 'W','i','n','d','o','w','3','2',0 };
+#endif
+#define REBARCLASSNAME WINELIB_NAME_AW(REBARCLASSNAME)
+
+#define RBS_TOOLTIPS 0x0100
+#define RBS_VARHEIGHT 0x0200
+#define RBS_BANDBORDERS 0x0400
+#define RBS_FIXEDORDER 0x0800
+#define RBS_REGISTERDROP 0x1000
+#define RBS_AUTOSIZE 0x2000
+#define RBS_VERTICALGRIPPER 0x4000
+#define RBS_DBLCLKTOGGLE 0x8000
+
+#define RBIM_IMAGELIST 0x00000001
+
+#define RBBIM_STYLE 0x00000001
+#define RBBIM_COLORS 0x00000002
+#define RBBIM_TEXT 0x00000004
+#define RBBIM_IMAGE 0x00000008
+#define RBBIM_CHILD 0x00000010
+#define RBBIM_CHILDSIZE 0x00000020
+#define RBBIM_SIZE 0x00000040
+#define RBBIM_BACKGROUND 0x00000080
+#define RBBIM_ID 0x00000100
+#define RBBIM_IDEALSIZE 0x00000200
+#define RBBIM_LPARAM 0x00000400
+#define RBBIM_HEADERSIZE 0x00000800
+
+#define RBBS_BREAK 0x00000001
+#define RBBS_FIXEDSIZE 0x00000002
+#define RBBS_CHILDEDGE 0x00000004
+#define RBBS_HIDDEN 0x00000008
+#define RBBS_NOVERT 0x00000010
+#define RBBS_FIXEDBMP 0x00000020
+#define RBBS_VARIABLEHEIGHT 0x00000040
+#define RBBS_GRIPPERALWAYS 0x00000080
+#define RBBS_NOGRIPPER 0x00000100
+
+#define RBNM_ID 0x00000001
+#define RBNM_STYLE 0x00000002
+#define RBNM_LPARAM 0x00000004
+
+#define RBHT_NOWHERE 0x0001
+#define RBHT_CAPTION 0x0002
+#define RBHT_CLIENT 0x0003
+#define RBHT_GRABBER 0x0004
+
+#define RB_INSERTBANDA (WM_USER+1)
+#define RB_INSERTBANDW (WM_USER+10)
+#define RB_INSERTBAND WINELIB_NAME_AW(RB_INSERTBAND)
+#define RB_DELETEBAND (WM_USER+2)
+#define RB_GETBARINFO (WM_USER+3)
+#define RB_SETBARINFO (WM_USER+4)
+#define RB_GETBANDINFO (WM_USER+5) /* just for compatibility */
+#define RB_SETBANDINFOA (WM_USER+6)
+#define RB_SETBANDINFOW (WM_USER+11)
+#define RB_SETBANDINFO WINELIB_NAME_AW(RB_SETBANDINFO)
+#define RB_SETPARENT (WM_USER+7)
+#define RB_HITTEST (WM_USER+8)
+#define RB_GETRECT (WM_USER+9)
+#define RB_GETBANDCOUNT (WM_USER+12)
+#define RB_GETROWCOUNT (WM_USER+13)
+#define RB_GETROWHEIGHT (WM_USER+14)
+#define RB_IDTOINDEX (WM_USER+16)
+#define RB_GETTOOLTIPS (WM_USER+17)
+#define RB_SETTOOLTIPS (WM_USER+18)
+#define RB_SETBKCOLOR (WM_USER+19)
+#define RB_GETBKCOLOR (WM_USER+20)
+#define RB_SETTEXTCOLOR (WM_USER+21)
+#define RB_GETTEXTCOLOR (WM_USER+22)
+#define RB_SIZETORECT (WM_USER+23)
+#define RB_BEGINDRAG (WM_USER+24)
+#define RB_ENDDRAG (WM_USER+25)
+#define RB_DRAGMOVE (WM_USER+26)
+#define RB_GETBARHEIGHT (WM_USER+27)
+#define RB_GETBANDINFOW (WM_USER+28)
+#define RB_GETBANDINFOA (WM_USER+29)
+#define RB_GETBANDINFO16 WINELIB_NAME_AW(RB_GETBANDINFO16)
+#define RB_MINIMIZEBAND (WM_USER+30)
+#define RB_MAXIMIZEBAND (WM_USER+31)
+#define RB_GETBANDBORDERS (WM_USER+34)
+#define RB_SHOWBAND (WM_USER+35)
+#define RB_SETPALETTE (WM_USER+37)
+#define RB_GETPALETTE (WM_USER+38)
+#define RB_MOVEBAND (WM_USER+39)
+#define RB_GETDROPTARGET CCM_GETDROPTARGET
+#define RB_SETCOLORSCHEME CCM_SETCOLORSCHEME
+#define RB_GETCOLORSCHEME CCM_GETCOLORSCHEME
+#define RB_SETUNICODEFORMAT CCM_SETUNICODEFORMAT
+#define RB_GETUNICODEFORMAT CCM_GETUNICODEFORMAT
+
+#define RBN_FIRST (0U-831U)
+#define RBN_LAST (0U-859U)
+#define RBN_HEIGHTCHANGE (RBN_FIRST-0)
+#define RBN_GETOBJECT (RBN_FIRST-1)
+#define RBN_LAYOUTCHANGED (RBN_FIRST-2)
+#define RBN_AUTOSIZE (RBN_FIRST-3)
+#define RBN_BEGINDRAG (RBN_FIRST-4)
+#define RBN_ENDDRAG (RBN_FIRST-5)
+#define RBN_DELETINGBAND (RBN_FIRST-6)
+#define RBN_DELETEDBAND (RBN_FIRST-7)
+#define RBN_CHILDSIZE (RBN_FIRST-8)
+
+typedef struct tagREBARINFO
+{
+ UINT cbSize;
+ UINT fMask;
+ HIMAGELIST himl;
+} REBARINFO, *LPREBARINFO;
+
+typedef struct tagREBARBANDINFOA
+{
+ UINT cbSize;
+ UINT fMask;
+ UINT fStyle;
+ COLORREF clrFore;
+ COLORREF clrBack;
+ LPSTR lpText;
+ UINT cch;
+ INT iImage;
+ HWND hwndChild;
+ UINT cxMinChild;
+ UINT cyMinChild;
+ UINT cx;
+ HBITMAP hbmBack;
+ UINT wID;
+ UINT cyChild;
+ UINT cyMaxChild;
+ UINT cyIntegral;
+ UINT cxIdeal;
+ LPARAM lParam;
+ UINT cxHeader;
+} REBARBANDINFOA, *LPREBARBANDINFOA;
+
+typedef REBARBANDINFOA const *LPCREBARBANDINFOA;
+
+typedef struct tagREBARBANDINFOW
+{
+ UINT cbSize;
+ UINT fMask;
+ UINT fStyle;
+ COLORREF clrFore;
+ COLORREF clrBack;
+ LPWSTR lpText;
+ UINT cch;
+ INT iImage;
+ HWND hwndChild;
+ UINT cxMinChild;
+ UINT cyMinChild;
+ UINT cx;
+ HBITMAP hbmBack;
+ UINT wID;
+ UINT cyChild;
+ UINT cyMaxChild;
+ UINT cyIntegral;
+ UINT cxIdeal;
+ LPARAM lParam;
+ UINT cxHeader;
+} REBARBANDINFOW, *LPREBARBANDINFOW;
+
+typedef REBARBANDINFOW const *LPCREBARBANDINFOW;
+
+#define REBARBANDINFO WINELIB_NAME_AW(REBARBANDINFO)
+#define LPREBARBANDINFO WINELIB_NAME_AW(LPREBARBANDINFO)
+#define LPCREBARBANDINFO WINELIB_NAME_AW(LPCREBARBANDINFO)
+
+#define REBARBANDINFO_V3_SIZEA CCSIZEOF_STRUCT(REBARBANDINFOA, wID)
+#define REBARBANDINFO_V3_SIZEW CCSIZEOF_STRUCT(REBARBANDINFOW, wID)
+#define REBARBANDINFO_V3_SIZE WINELIB_NAME_AW(REBARBANDINFO_V3_SIZE)
+
+typedef struct tagNMREBARCHILDSIZE
+{
+ NMHDR hdr;
+ UINT uBand;
+ UINT wID;
+ RECT rcChild;
+ RECT rcBand;
+} NMREBARCHILDSIZE, *LPNMREBARCHILDSIZE;
+
+typedef struct tagNMREBAR
+{
+ NMHDR hdr;
+ DWORD dwMask;
+ UINT uBand;
+ UINT fStyle;
+ UINT wID;
+ LPARAM lParam;
+} NMREBAR, *LPNMREBAR;
+
+typedef struct tagNMRBAUTOSIZE
+{
+ NMHDR hdr;
+ BOOL fChanged;
+ RECT rcTarget;
+ RECT rcActual;
+} NMRBAUTOSIZE, *LPNMRBAUTOSIZE;
+
+typedef struct _RB_HITTESTINFO
+{
+ POINT pt;
+ UINT flags;
+ INT iBand;
+} RBHITTESTINFO, *LPRBHITTESTINFO;
+
+
+/* Trackbar control */
+
+#define TRACKBAR_CLASS16 "msctls_trackbar"
+#define TRACKBAR_CLASSA "msctls_trackbar32"
+#if defined(__GNUC__)
+# define TRACKBAR_CLASSW (const WCHAR []){ 'm','s','c','t','l','s','_', \
+ 't','r','a','c','k','b','a','r','3','2',0 }
+#elif defined(_MSC_VER)
+# define TRACKBAR_CLASSW L"msctls_trackbar32"
+#else
+static const WCHAR TRACKBAR_CLASSW[] = { 'm','s','c','t','l','s','_',
+ 't','r','a','c','k','b','a','r','3','2',0 };
+#endif
+#define TRACKBAR_CLASS WINELIB_NAME_AW(TRACKBAR_CLASS)
+
+#define TBS_AUTOTICKS 0x0001
+#define TBS_VERT 0x0002
+#define TBS_HORZ 0x0000
+#define TBS_TOP 0x0004
+#define TBS_BOTTOM 0x0000
+#define TBS_LEFT 0x0004
+#define TBS_RIGHT 0x0000
+#define TBS_BOTH 0x0008
+#define TBS_NOTICKS 0x0010
+#define TBS_ENABLESELRANGE 0x0020
+#define TBS_FIXEDLENGTH 0x0040
+#define TBS_NOTHUMB 0x0080
+#define TBS_TOOLTIPS 0x0100
+#define TBS_REVERSED 0x0200
+#define TBS_DOWNISLEFT 0x0400
+
+#define TBTS_TOP 0
+#define TBTS_LEFT 1
+#define TBTS_BOTTOM 2
+#define TBTS_RIGHT 3
+
+#define TB_LINEUP 0
+#define TB_LINEDOWN 1
+#define TB_PAGEUP 2
+#define TB_PAGEDOWN 3
+#define TB_THUMBPOSITION 4
+#define TB_THUMBTRACK 5
+#define TB_TOP 6
+#define TB_BOTTOM 7
+#define TB_ENDTRACK 8
+
+#define TBCD_TICS 0x0001
+#define TBCD_THUMB 0x0002
+#define TBCD_CHANNEL 0x0003
+
+#define TBM_GETPOS (WM_USER)
+#define TBM_GETRANGEMIN (WM_USER+1)
+#define TBM_GETRANGEMAX (WM_USER+2)
+#define TBM_GETTIC (WM_USER+3)
+#define TBM_SETTIC (WM_USER+4)
+#define TBM_SETPOS (WM_USER+5)
+#define TBM_SETRANGE (WM_USER+6)
+#define TBM_SETRANGEMIN (WM_USER+7)
+#define TBM_SETRANGEMAX (WM_USER+8)
+#define TBM_CLEARTICS (WM_USER+9)
+#define TBM_SETSEL (WM_USER+10)
+#define TBM_SETSELSTART (WM_USER+11)
+#define TBM_SETSELEND (WM_USER+12)
+#define TBM_GETPTICS (WM_USER+14)
+#define TBM_GETTICPOS (WM_USER+15)
+#define TBM_GETNUMTICS (WM_USER+16)
+#define TBM_GETSELSTART (WM_USER+17)
+#define TBM_GETSELEND (WM_USER+18)
+#define TBM_CLEARSEL (WM_USER+19)
+#define TBM_SETTICFREQ (WM_USER+20)
+#define TBM_SETPAGESIZE (WM_USER+21)
+#define TBM_GETPAGESIZE (WM_USER+22)
+#define TBM_SETLINESIZE (WM_USER+23)
+#define TBM_GETLINESIZE (WM_USER+24)
+#define TBM_GETTHUMBRECT (WM_USER+25)
+#define TBM_GETCHANNELRECT (WM_USER+26)
+#define TBM_SETTHUMBLENGTH (WM_USER+27)
+#define TBM_GETTHUMBLENGTH (WM_USER+28)
+#define TBM_SETTOOLTIPS (WM_USER+29)
+#define TBM_GETTOOLTIPS (WM_USER+30)
+#define TBM_SETTIPSIDE (WM_USER+31)
+#define TBM_SETBUDDY (WM_USER+32)
+#define TBM_GETBUDDY (WM_USER+33)
+#define TBM_SETUNICODEFORMAT CCM_SETUNICODEFORMAT
+#define TBM_GETUNICODEFORMAT CCM_GETUNICODEFORMAT
+
+
+/* Pager control */
+
+#define WC_PAGESCROLLERA "SysPager"
+#if defined(__GNUC__)
+# define WC_PAGESCROLLERW (const WCHAR []){ 'S','y','s','P','a','g','e','r',0 }
+#elif defined(_MSC_VER)
+# define WC_PAGESCROLLERW L"SysPager"
+#else
+static const WCHAR WC_PAGESCROLLERW[] = { 'S','y','s','P','a','g','e','r',0 };
+#endif
+#define WC_PAGESCROLLER WINELIB_NAME_AW(WC_PAGESCROLLER)
+
+#define PGS_VERT 0x00000000
+#define PGS_HORZ 0x00000001
+#define PGS_AUTOSCROLL 0x00000002
+#define PGS_DRAGNDROP 0x00000004
+
+#define PGF_INVISIBLE 0
+#define PGF_NORMAL 1
+#define PGF_GRAYED 2
+#define PGF_DEPRESSED 4
+#define PGF_HOT 8
+
+#define PGB_TOPORLEFT 0
+#define PGB_BOTTOMORRIGHT 1
+
+/* only used with PGN_SCROLL */
+#define PGF_SCROLLUP 1
+#define PGF_SCROLLDOWN 2
+#define PGF_SCROLLLEFT 4
+#define PGF_SCROLLRIGHT 8
+
+#define PGK_SHIFT 1
+#define PGK_CONTROL 2
+#define PGK_MENU 4
+
+/* only used with PGN_CALCSIZE */
+#define PGF_CALCWIDTH 1
+#define PGF_CALCHEIGHT 2
+
+#define PGM_FIRST 0x1400
+#define PGM_SETCHILD (PGM_FIRST+1)
+#define PGM_RECALCSIZE (PGM_FIRST+2)
+#define PGM_FORWARDMOUSE (PGM_FIRST+3)
+#define PGM_SETBKCOLOR (PGM_FIRST+4)
+#define PGM_GETBKCOLOR (PGM_FIRST+5)
+#define PGM_SETBORDER (PGM_FIRST+6)
+#define PGM_GETBORDER (PGM_FIRST+7)
+#define PGM_SETPOS (PGM_FIRST+8)
+#define PGM_GETPOS (PGM_FIRST+9)
+#define PGM_SETBUTTONSIZE (PGM_FIRST+10)
+#define PGM_GETBUTTONSIZE (PGM_FIRST+11)
+#define PGM_GETBUTTONSTATE (PGM_FIRST+12)
+#define PGM_GETDROPTARGET CCM_GETDROPTARGET
+
+#define PGN_FIRST (0U-900U)
+#define PGN_LAST (0U-950U)
+#define PGN_SCROLL (PGN_FIRST-1)
+#define PGN_CALCSIZE (PGN_FIRST-2)
+
+#include "pshpack1.h"
+
+typedef struct
+{
+ NMHDR hdr;
+ WORD fwKeys;
+ RECT rcParent;
+ INT iDir;
+ INT iXpos;
+ INT iYpos;
+ INT iScroll;
+} NMPGSCROLL, *LPNMPGSCROLL;
+
+#include "poppack.h"
+
+typedef struct
+{
+ NMHDR hdr;
+ DWORD dwFlag;
+ INT iWidth;
+ INT iHeight;
+} NMPGCALCSIZE, *LPNMPGCALCSIZE;
+
+
+/* Treeview control */
+
+#define WC_TREEVIEWA "SysTreeView32"
+#if defined(__GNUC__)
+# define WC_TREEVIEWW (const WCHAR []){ 'S','y','s', \
+ 'T','r','e','e','V','i','e','w','3','2',0 }
+#elif defined(_MSC_VER)
+# define WC_TREEVIEWW L"SysTreeView32"
+#else
+static const WCHAR WC_TREEVIEWW[] = { 'S','y','s',
+ 'T','r','e','e','V','i','e','w','3','2',0 };
+#endif
+#define WC_TREEVIEW WINELIB_NAME_AW(WC_TREEVIEW)
+
+#define TVSIL_NORMAL 0
+#define TVSIL_STATE 2
+
+#define TV_FIRST 0x1100
+#define TVM_INSERTITEMA (TV_FIRST+0)
+#define TVM_INSERTITEMW (TV_FIRST+50)
+#define TVM_INSERTITEM WINELIB_NAME_AW(TVM_INSERTITEM)
+#define TVM_DELETEITEM (TV_FIRST+1)
+#define TVM_EXPAND (TV_FIRST+2)
+#define TVM_GETITEMRECT (TV_FIRST+4)
+#define TVM_GETCOUNT (TV_FIRST+5)
+#define TVM_GETINDENT (TV_FIRST+6)
+#define TVM_SETINDENT (TV_FIRST+7)
+#define TVM_GETIMAGELIST (TV_FIRST+8)
+#define TVM_SETIMAGELIST (TV_FIRST+9)
+#define TVM_GETNEXTITEM (TV_FIRST+10)
+#define TVM_SELECTITEM (TV_FIRST+11)
+#define TVM_GETITEMA (TV_FIRST+12)
+#define TVM_GETITEMW (TV_FIRST+62)
+#define TVM_GETITEM WINELIB_NAME_AW(TVM_GETITEM)
+#define TVM_SETITEMA (TV_FIRST+13)
+#define TVM_SETITEMW (TV_FIRST+63)
+#define TVM_SETITEM WINELIB_NAME_AW(TVM_SETITEM)
+#define TVM_EDITLABELA (TV_FIRST+14)
+#define TVM_EDITLABELW (TV_FIRST+65)
+#define TVM_EDITLABEL WINELIB_NAME_AW(TVM_EDITLABEL)
+#define TVM_GETEDITCONTROL (TV_FIRST+15)
+#define TVM_GETVISIBLECOUNT (TV_FIRST+16)
+#define TVM_HITTEST (TV_FIRST+17)
+#define TVM_CREATEDRAGIMAGE (TV_FIRST+18)
+#define TVM_SORTCHILDREN (TV_FIRST+19)
+#define TVM_ENSUREVISIBLE (TV_FIRST+20)
+#define TVM_SORTCHILDRENCB (TV_FIRST+21)
+#define TVM_ENDEDITLABELNOW (TV_FIRST+22)
+#define TVM_GETISEARCHSTRINGA (TV_FIRST+23)
+#define TVM_GETISEARCHSTRINGW (TV_FIRST+64)
+#define TVM_GETISEARCHSTRING WINELIB_NAME_AW(TVM_GETISEARCHSTRING)
+#define TVM_SETTOOLTIPS (TV_FIRST+24)
+#define TVM_GETTOOLTIPS (TV_FIRST+25)
+#define TVM_SETINSERTMARK (TV_FIRST+26)
+#define TVM_SETITEMHEIGHT (TV_FIRST+27)
+#define TVM_GETITEMHEIGHT (TV_FIRST+28)
+#define TVM_SETBKCOLOR (TV_FIRST+29)
+#define TVM_SETTEXTCOLOR (TV_FIRST+30)
+#define TVM_GETBKCOLOR (TV_FIRST+31)
+#define TVM_GETTEXTCOLOR (TV_FIRST+32)
+#define TVM_SETSCROLLTIME (TV_FIRST+33)
+#define TVM_GETSCROLLTIME (TV_FIRST+34)
+#define TVM_UNKNOWN35 (TV_FIRST+35)
+#define TVM_UNKNOWN36 (TV_FIRST+36)
+#define TVM_SETINSERTMARKCOLOR (TV_FIRST+37)
+#define TVM_GETINSERTMARKCOLOR (TV_FIRST+38)
+#define TVM_GETITEMSTATE (TV_FIRST+39)
+#define TVM_SETLINECOLOR (TV_FIRST+40)
+#define TVM_GETLINECOLOR (TV_FIRST+41)
+#define TVM_SETUNICODEFORMAT CCM_SETUNICODEFORMAT
+#define TVM_GETUNICODEFORMAT CCM_GETUNICODEFORMAT
+
+
+
+#define TVN_FIRST (0U-400U)
+#define TVN_LAST (0U-499U)
+
+#define TVN_SELCHANGINGA (TVN_FIRST-1)
+#define TVN_SELCHANGINGW (TVN_FIRST-50)
+#define TVN_SELCHANGING WINELIB_NAME_AW(TVN_SELCHANGING)
+
+#define TVN_SELCHANGEDA (TVN_FIRST-2)
+#define TVN_SELCHANGEDW (TVN_FIRST-51)
+#define TVN_SELCHANGED WINELIB_NAME_AW(TVN_SELCHANGED)
+
+#define TVN_GETDISPINFOA (TVN_FIRST-3)
+#define TVN_GETDISPINFOW (TVN_FIRST-52)
+#define TVN_GETDISPINFO WINELIB_NAME_AW(TVN_GETDISPINFO)
+
+#define TVN_SETDISPINFOA (TVN_FIRST-4)
+#define TVN_SETDISPINFOW (TVN_FIRST-53)
+#define TVN_SETDISPINFO WINELIB_NAME_AW(TVN_SETDISPINFO)
+
+#define TVN_ITEMEXPANDINGA (TVN_FIRST-5)
+#define TVN_ITEMEXPANDINGW (TVN_FIRST-54)
+#define TVN_ITEMEXPANDING WINELIB_NAME_AW(TVN_ITEMEXPANDING)
+
+#define TVN_ITEMEXPANDEDA (TVN_FIRST-6)
+#define TVN_ITEMEXPANDEDW (TVN_FIRST-55)
+#define TVN_ITEMEXPANDED WINELIB_NAME_AW(TVN_ITEMEXPANDED)
+
+#define TVN_BEGINDRAGA (TVN_FIRST-7)
+#define TVN_BEGINDRAGW (TVN_FIRST-56)
+#define TVN_BEGINDRAG WINELIB_NAME_AW(TVN_BEGINDRAG)
+
+#define TVN_BEGINRDRAGA (TVN_FIRST-8)
+#define TVN_BEGINRDRAGW (TVN_FIRST-57)
+#define TVN_BEGINRDRAG WINELIB_NAME_AW(TVN_BEGINRDRAG)
+
+#define TVN_DELETEITEMA (TVN_FIRST-9)
+#define TVN_DELETEITEMW (TVN_FIRST-58)
+#define TVN_DELETEITEM WINELIB_NAME_AW(TVN_DELETEITEM)
+
+#define TVN_BEGINLABELEDITA (TVN_FIRST-10)
+#define TVN_BEGINLABELEDITW (TVN_FIRST-59)
+#define TVN_BEGINLABELEDIT WINELIB_NAME_AW(TVN_BEGINLABELEDIT)
+
+#define TVN_ENDLABELEDITA (TVN_FIRST-11)
+#define TVN_ENDLABELEDITW (TVN_FIRST-60)
+#define TVN_ENDLABELEDIT WINELIB_NAME_AW(TVN_ENDLABELEDIT)
+
+#define TVN_KEYDOWN (TVN_FIRST-12)
+
+#define TVN_GETINFOTIPA (TVN_FIRST-13)
+#define TVN_GETINFOTIPW (TVN_FIRST-14)
+#define TVN_GETINFOTIP WINELIB_NAME_AW(TVN_GETINFOTIP)
+
+#define TVN_SINGLEEXPAND (TVN_FIRST-15)
+
+
+
+
+
+#define TVIF_TEXT 0x0001
+#define TVIF_IMAGE 0x0002
+#define TVIF_PARAM 0x0004
+#define TVIF_STATE 0x0008
+#define TVIF_HANDLE 0x0010
+#define TVIF_SELECTEDIMAGE 0x0020
+#define TVIF_CHILDREN 0x0040
+#define TVIF_INTEGRAL 0x0080
+#define TVIF_DI_SETITEM 0x1000
+
+#define TVI_ROOT ((HTREEITEM)0xffff0000) /* -65536 */
+#define TVI_FIRST ((HTREEITEM)0xffff0001) /* -65535 */
+#define TVI_LAST ((HTREEITEM)0xffff0002) /* -65534 */
+#define TVI_SORT ((HTREEITEM)0xffff0003) /* -65533 */
+
+#define TVIS_FOCUSED 0x0001
+#define TVIS_SELECTED 0x0002
+#define TVIS_CUT 0x0004
+#define TVIS_DROPHILITED 0x0008
+#define TVIS_BOLD 0x0010
+#define TVIS_EXPANDED 0x0020
+#define TVIS_EXPANDEDONCE 0x0040
+#define TVIS_EXPANDPARTIAL 0x0080
+#define TVIS_OVERLAYMASK 0x0f00
+#define TVIS_STATEIMAGEMASK 0xf000
+#define TVIS_USERMASK 0xf000
+
+#define TVHT_NOWHERE 0x0001
+#define TVHT_ONITEMICON 0x0002
+#define TVHT_ONITEMLABEL 0x0004
+#define TVHT_ONITEMINDENT 0x0008
+#define TVHT_ONITEMBUTTON 0x0010
+#define TVHT_ONITEMRIGHT 0x0020
+#define TVHT_ONITEMSTATEICON 0x0040
+#define TVHT_ONITEM 0x0046
+#define TVHT_ABOVE 0x0100
+#define TVHT_BELOW 0x0200
+#define TVHT_TORIGHT 0x0400
+#define TVHT_TOLEFT 0x0800
+
+#define TVS_HASBUTTONS 0x0001
+#define TVS_HASLINES 0x0002
+#define TVS_LINESATROOT 0x0004
+#define TVS_EDITLABELS 0x0008
+#define TVS_DISABLEDRAGDROP 0x0010
+#define TVS_SHOWSELALWAYS 0x0020
+#define TVS_RTLREADING 0x0040
+#define TVS_NOTOOLTIPS 0x0080
+#define TVS_CHECKBOXES 0x0100
+#define TVS_TRACKSELECT 0x0200
+#define TVS_SINGLEEXPAND 0x0400
+#define TVS_INFOTIP 0x0800
+#define TVS_FULLROWSELECT 0x1000
+#define TVS_NOSCROLL 0x2000
+#define TVS_NONEVENHEIGHT 0x4000
+#define TVS_NOHSCROLL 0x8000
+
+#define TVS_SHAREDIMAGELISTS 0x0000
+#define TVS_PRIVATEIMAGELISTS 0x0400
+
+
+#define TVE_COLLAPSE 0x0001
+#define TVE_EXPAND 0x0002
+#define TVE_TOGGLE 0x0003
+#define TVE_EXPANDPARTIAL 0x4000
+#define TVE_COLLAPSERESET 0x8000
+
+#define TVGN_ROOT 0
+#define TVGN_NEXT 1
+#define TVGN_PREVIOUS 2
+#define TVGN_PARENT 3
+#define TVGN_CHILD 4
+#define TVGN_FIRSTVISIBLE 5
+#define TVGN_NEXTVISIBLE 6
+#define TVGN_PREVIOUSVISIBLE 7
+#define TVGN_DROPHILITE 8
+#define TVGN_CARET 9
+#define TVGN_LASTVISIBLE 10
+
+#define TVC_UNKNOWN 0x00
+#define TVC_BYMOUSE 0x01
+#define TVC_BYKEYBOARD 0x02
+
+
+typedef struct _TREEITEM *HTREEITEM;
+
+typedef struct {
+ UINT mask;
+ HTREEITEM hItem;
+ UINT state;
+ UINT stateMask;
+ LPSTR pszText;
+ INT cchTextMax;
+ INT iImage;
+ INT iSelectedImage;
+ INT cChildren;
+ LPARAM lParam;
+} TVITEMA, *LPTVITEMA;
+
+typedef struct {
+ UINT mask;
+ HTREEITEM hItem;
+ UINT state;
+ UINT stateMask;
+ LPWSTR pszText;
+ INT cchTextMax;
+ INT iImage;
+ INT iSelectedImage;
+ INT cChildren;
+ LPARAM lParam;
+} TVITEMW, *LPTVITEMW;
+
+#define TV_ITEMA TVITEMA
+#define TV_ITEMW TVITEMW
+#define LPTV_ITEMA LPTVITEMA
+#define LPTV_ITEMW LPTVITEMW
+
+#define TVITEM WINELIB_NAME_AW(TVITEM)
+#define LPTVITEM WINELIB_NAME_AW(LPTVITEM)
+#define TV_ITEM WINELIB_NAME_AW(TV_ITEM)
+#define LPTV_ITEM WINELIB_NAME_AW(LPTV_ITEM)
+
+typedef struct {
+ UINT mask;
+ HTREEITEM hItem;
+ UINT state;
+ UINT stateMask;
+ LPSTR pszText;
+ INT cchTextMax;
+ INT iImage;
+ INT iSelectedImage;
+ INT cChildren;
+ LPARAM lParam;
+ INT iIntegral;
+} TVITEMEXA, *LPTVITEMEXA;
+
+typedef struct {
+ UINT mask;
+ HTREEITEM hItem;
+ UINT state;
+ UINT stateMask;
+ LPWSTR pszText;
+ INT cchTextMax;
+ INT iImage;
+ INT iSelectedImage;
+ INT cChildren;
+ LPARAM lParam;
+ INT iIntegral;
+} TVITEMEXW, *LPTVITEMEXW;
+
+#define TVITEMEX WINELIB_NAME_AW(TVITEMEX)
+#define LPTVITEMEX WINELIB_NAME_AW(LPTVITEMEX)
+
+typedef struct tagTVINSERTSTRUCTA {
+ HTREEITEM hParent;
+ HTREEITEM hInsertAfter;
+ union {
+ TVITEMEXA itemex;
+ TVITEMA item;
+ } DUMMYUNIONNAME;
+} TVINSERTSTRUCTA, *LPTVINSERTSTRUCTA;
+
+typedef struct tagTVINSERTSTRUCTW {
+ HTREEITEM hParent;
+ HTREEITEM hInsertAfter;
+ union {
+ TVITEMEXW itemex;
+ TVITEMW item;
+ } DUMMYUNIONNAME;
+} TVINSERTSTRUCTW, *LPTVINSERTSTRUCTW;
+
+#define TVINSERTSTRUCT WINELIB_NAME_AW(TVINSERTSTRUCT)
+#define LPTVINSERTSTRUCT WINELIB_NAME_AW(LPTVINSERTSTRUCT)
+
+#define TVINSERTSTRUCT_V1_SIZEA CCSIZEOF_STRUCT(TVINSERTSTRUCTA, item)
+#define TVINSERTSTRUCT_V1_SIZEW CCSIZEOF_STRUCT(TVINSERTSTRUCTW, item)
+#define TVINSERTSTRUCT_V1_SIZE WINELIB_NAME_AW(TVINSERTSTRUCT_V1_SIZE)
+
+#define TV_INSERTSTRUCT TVINSERTSTRUCT
+#define TV_INSERTSTRUCTA TVINSERTSTRUCTA
+#define TV_INSERTSTRUCTW TVINSERTSTRUCTW
+#define LPTV_INSERTSTRUCT LPTVINSERTSTRUCT
+#define LPTV_INSERTSTRUCTA LPTVINSERTSTRUCTA
+#define LPTV_INSERTSTRUCTW LPTVINSERTSTRUCTW
+
+
+
+typedef struct tagNMTREEVIEWA {
+ NMHDR hdr;
+ UINT action;
+ TVITEMA itemOld;
+ TVITEMA itemNew;
+ POINT ptDrag;
+} NMTREEVIEWA, *LPNMTREEVIEWA;
+
+typedef struct tagNMTREEVIEWW {
+ NMHDR hdr;
+ UINT action;
+ TVITEMW itemOld;
+ TVITEMW itemNew;
+ POINT ptDrag;
+} NMTREEVIEWW, *LPNMTREEVIEWW;
+
+#define NMTREEVIEW WINELIB_NAME_AW(NMTREEVIEW)
+#define NM_TREEVIEW WINELIB_NAME_AW(NMTREEVIEW)
+#define LPNMTREEVIEW WINELIB_NAME_AW(LPNMTREEVIEW)
+
+#define LPNM_TREEVIEW LPNMTREEVIEW
+
+typedef struct tagTVDISPINFOA {
+ NMHDR hdr;
+ TVITEMA item;
+} NMTVDISPINFOA, *LPNMTVDISPINFOA;
+
+typedef struct tagTVDISPINFOW {
+ NMHDR hdr;
+ TVITEMW item;
+} NMTVDISPINFOW, *LPNMTVDISPINFOW;
+
+#define NMTVDISPINFO WINELIB_NAME_AW(NMTVDISPINFO)
+#define LPNMTVDISPINFO WINELIB_NAME_AW(LPNMTVDISPINFO)
+#define TV_DISPINFO NMTVDISPINFO
+
+typedef INT (CALLBACK *PFNTVCOMPARE)(LPARAM, LPARAM, LPARAM);
+
+typedef struct tagTVSORTCB
+{
+ HTREEITEM hParent;
+ PFNTVCOMPARE lpfnCompare;
+ LPARAM lParam;
+} TVSORTCB, *LPTVSORTCB;
+
+#define TV_SORTCB TVSORTCB
+#define LPTV_SORTCB LPTVSORTCB
+
+typedef struct tagTVHITTESTINFO {
+ POINT pt;
+ UINT flags;
+ HTREEITEM hItem;
+} TVHITTESTINFO, *LPTVHITTESTINFO;
+
+#define TV_HITTESTINFO TVHITTESTINFO
+
+
+/* Custom Draw Treeview */
+
+#define NMTVCUSTOMDRAW_V3_SIZE CCSIZEOF_STRUCT(NMTVCUSTOMDRAW, clrTextBk)
+
+#define TVCDRF_NOIMAGES 0x00010000
+
+typedef struct tagNMTVCUSTOMDRAW
+{
+ NMCUSTOMDRAW nmcd;
+ COLORREF clrText;
+ COLORREF clrTextBk;
+ INT iLevel; /* IE>0x0400 */
+} NMTVCUSTOMDRAW, *LPNMTVCUSTOMDRAW;
+
+/* Treeview tooltips */
+
+typedef struct tagNMTVGETINFOTIPA
+{
+ NMHDR hdr;
+ LPSTR pszText;
+ INT cchTextMax;
+ HTREEITEM hItem;
+ LPARAM lParam;
+} NMTVGETINFOTIPA, *LPNMTVGETINFOTIPA;
+
+typedef struct tagNMTVGETINFOTIPW
+{
+ NMHDR hdr;
+ LPWSTR pszText;
+ INT cchTextMax;
+ HTREEITEM hItem;
+ LPARAM lParam;
+} NMTVGETINFOTIPW, *LPNMTVGETINFOTIPW;
+
+#define NMTVGETINFOTIP WINELIB_NAME_AW(NMTVGETINFOTIP)
+#define LPNMTVGETINFOTIP WINELIB_NAME_AW(LPNMTVGETINFOTIP)
+
+#include "pshpack1.h"
+typedef struct tagTVKEYDOWN
+{
+ NMHDR hdr;
+ WORD wVKey;
+ UINT flags;
+} NMTVKEYDOWN, *LPNMTVKEYDOWN;
+#include "poppack.h"
+
+#define TV_KEYDOWN NMTVKEYDOWN
+
+#define TreeView_InsertItemA(hwnd, phdi) \
+ (HTREEITEM)SNDMSGA((hwnd), TVM_INSERTITEMA, 0, \
+ (LPARAM)(LPTVINSERTSTRUCTA)(phdi))
+#define TreeView_InsertItemW(hwnd,phdi) \
+ (HTREEITEM)SNDMSGW((hwnd), TVM_INSERTITEMW, 0, \
+ (LPARAM)(LPTVINSERTSTRUCTW)(phdi))
+#define TreeView_InsertItem WINELIB_NAME_AW(TreeView_InsertItem)
+
+#define TreeView_DeleteItem(hwnd, hItem) \
+ (BOOL)SNDMSGA((hwnd), TVM_DELETEITEM, 0, (LPARAM)(HTREEITEM)(hItem))
+#define TreeView_DeleteAllItems(hwnd) \
+ (BOOL)SNDMSGA((hwnd), TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT)
+#define TreeView_Expand(hwnd, hitem, code) \
+ (BOOL)SNDMSGA((hwnd), TVM_EXPAND, (WPARAM)code, \
+ (LPARAM)(HTREEITEM)(hitem))
+
+#define TreeView_GetItemRect(hwnd, hitem, prc, code) \
+ (*(HTREEITEM *)prc = (hitem), (BOOL)SNDMSGA((hwnd), \
+ TVM_GETITEMRECT, (WPARAM)(code), (LPARAM)(RECT *)(prc)))
+
+#define TreeView_GetCount(hwnd) \
+ (UINT)SNDMSGA((hwnd), TVM_GETCOUNT, 0, 0)
+#define TreeView_GetIndent(hwnd) \
+ (UINT)SNDMSGA((hwnd), TVM_GETINDENT, 0, 0)
+#define TreeView_SetIndent(hwnd, indent) \
+ (BOOL)SNDMSGA((hwnd), TVM_SETINDENT, (WPARAM)indent, 0)
+
+#define TreeView_GetImageList(hwnd, iImage) \
+ (HIMAGELIST)SNDMSGA((hwnd), TVM_GETIMAGELIST, iImage, 0)
+
+#define TreeView_SetImageList(hwnd, himl, iImage) \
+ (HIMAGELIST)SNDMSGA((hwnd), TVM_SETIMAGELIST, iImage, \
+ (LPARAM)(UINT)(HIMAGELIST)(himl))
+
+#define TreeView_GetNextItem(hwnd, hitem, code) \
+ (HTREEITEM)SNDMSGA((hwnd), TVM_GETNEXTITEM, (WPARAM)code,\
+(LPARAM)(HTREEITEM) (hitem))
+
+#define TreeView_GetChild(hwnd, hitem) \
+ TreeView_GetNextItem(hwnd, hitem , TVGN_CHILD)
+#define TreeView_GetNextSibling(hwnd, hitem) \
+ TreeView_GetNextItem(hwnd, hitem , TVGN_NEXT)
+#define TreeView_GetPrevSibling(hwnd, hitem) \
+ TreeView_GetNextItem(hwnd, hitem , TVGN_PREVIOUS)
+#define TreeView_GetParent(hwnd, hitem) \
+ TreeView_GetNextItem(hwnd, hitem , TVGN_PARENT)
+#define TreeView_GetFirstVisible(hwnd) \
+ TreeView_GetNextItem(hwnd, NULL, TVGN_FIRSTVISIBLE)
+#define TreeView_GetLastVisible(hwnd) \
+ TreeView_GetNextItem(hwnd, NULL, TVGN_LASTVISIBLE)
+#define TreeView_GetNextVisible(hwnd, hitem) \
+ TreeView_GetNextItem(hwnd, hitem , TVGN_NEXTVISIBLE)
+#define TreeView_GetPrevVisible(hwnd, hitem) \
+ TreeView_GetNextItem(hwnd, hitem , TVGN_PREVIOUSVISIBLE)
+#define TreeView_GetSelection(hwnd) \
+ TreeView_GetNextItem(hwnd, NULL, TVGN_CARET)
+#define TreeView_GetDropHilight(hwnd) \
+ TreeView_GetNextItem(hwnd, NULL, TVGN_DROPHILITE)
+#define TreeView_GetRoot(hwnd) \
+ TreeView_GetNextItem(hwnd, NULL, TVGN_ROOT)
+#define TreeView_GetLastVisible(hwnd) \
+ TreeView_GetNextItem(hwnd, NULL, TVGN_LASTVISIBLE)
+
+
+#define TreeView_Select(hwnd, hitem, code) \
+ (UINT)SNDMSGA((hwnd), TVM_SELECTITEM, (WPARAM)code, \
+(LPARAM)(UINT)(hitem))
+
+
+#define TreeView_SelectItem(hwnd, hitem) \
+ TreeView_Select(hwnd, hitem, TVGN_CARET)
+#define TreeView_SelectDropTarget(hwnd, hitem) \
+ TreeView_Select(hwnd, hitem, TVGN_DROPHILITE)
+#define TreeView_SelectSetFirstVisible(hwnd, hitem) \
+ TreeView_Select(hwnd, hitem, TVGN_FIRSTVISIBLE)
+
+
+#define TreeView_GetItemA(hwnd, pitem) \
+ (BOOL)SNDMSGA((hwnd), TVM_GETITEMA, 0, (LPARAM) (TVITEMA *)(pitem))
+#define TreeView_GetItemW(hwnd, pitem) \
+ (BOOL)SNDMSGW((hwnd), TVM_GETITEMA, 0, (LPARAM) (TVITEMA *)(pitem))
+#define TreeView_GetItem WINELIB_NAME_AW(TreeView_GetItem)
+
+#define TreeView_SetItemA(hwnd, pitem) \
+ (BOOL)SNDMSGA((hwnd), TVM_SETITEMA, 0, (LPARAM)(const TVITEMA *)(pitem))
+#define TreeView_SetItemW(hwnd, pitem) \
+ (BOOL)SNDMSGW((hwnd), TVM_SETITEMA, 0, (LPARAM)(const TVITEMA *)(pitem))
+#define TreeView_SetItem WINELIB_NAME_AW(TreeView_SetItem)
+
+#define TreeView_EditLabel(hwnd, hitem) \
+ (HWND)SNDMSGA((hwnd), TVM_EDITLABEL, 0, (LPARAM)(HTREEITEM)(hitem))
+
+#define TreeView_GetEditControl(hwnd) \
+ (HWND)SNDMSGA((hwnd), TVM_GETEDITCONTROL, 0, 0)
+
+#define TreeView_GetVisibleCount(hwnd) \
+ (UINT)SNDMSGA((hwnd), TVM_GETVISIBLECOUNT, 0, 0)
+
+#define TreeView_HitTest(hwnd, lpht) \
+ (HTREEITEM)SNDMSGA((hwnd), TVM_HITTEST, 0,\
+(LPARAM)(LPTVHITTESTINFO)(lpht))
+
+#define TreeView_CreateDragImage(hwnd, hitem) \
+ (HIMAGELIST)SNDMSGA((hwnd), TVM_CREATEDRAGIMAGE, 0,\
+(LPARAM)(HTREEITEM)(hitem))
+
+#define TreeView_SortChildren(hwnd, hitem, recurse) \
+ (BOOL)SNDMSGA((hwnd), TVM_SORTCHILDREN, (WPARAM)recurse,\
+(LPARAM)(HTREEITEM)(hitem))
+
+#define TreeView_EnsureVisible(hwnd, hitem) \
+ (BOOL)SNDMSGA((hwnd), TVM_ENSUREVISIBLE, 0, (LPARAM)(UINT)(hitem))
+
+#define TreeView_SortChildrenCB(hwnd, psort, recurse) \
+ (BOOL)SNDMSGA((hwnd), TVM_SORTCHILDRENCB, (WPARAM)recurse, \
+ (LPARAM)(LPTV_SORTCB)(psort))
+
+#define TreeView_EndEditLabelNow(hwnd, fCancel) \
+ (BOOL)SNDMSGA((hwnd), TVM_ENDEDITLABELNOW, (WPARAM)fCancel, 0)
+
+#define TreeView_GetISearchString(hwnd, lpsz) \
+ (BOOL)SNDMSGA((hwnd), TVM_GETISEARCHSTRING, 0, \
+ (LPARAM)(LPTSTR)lpsz)
+
+#define TreeView_SetToolTips(hwnd, hwndTT) \
+ (HWND)SNDMSGA((hwnd), TVM_SETTOOLTIPS, (WPARAM)(hwndTT), 0)
+
+#define TreeView_GetToolTips(hwnd) \
+ (HWND)SNDMSGA((hwnd), TVM_GETTOOLTIPS, 0, 0)
+
+#define TreeView_SetItemHeight(hwnd, iHeight) \
+ (INT)SNDMSGA((hwnd), TVM_SETITEMHEIGHT, (WPARAM)iHeight, 0)
+
+#define TreeView_GetItemHeight(hwnd) \
+ (INT)SNDMSGA((hwnd), TVM_GETITEMHEIGHT, 0, 0)
+
+#define TreeView_SetBkColor(hwnd, clr) \
+ (COLORREF)SNDMSGA((hwnd), TVM_SETBKCOLOR, 0, (LPARAM)clr)
+
+#define TreeView_SetTextColor(hwnd, clr) \
+ (COLORREF)SNDMSGA((hwnd), TVM_SETTEXTCOLOR, 0, (LPARAM)clr)
+
+#define TreeView_GetBkColor(hwnd) \
+ (COLORREF)SNDMSGA((hwnd), TVM_GETBKCOLOR, 0, 0)
+
+#define TreeView_GetTextColor(hwnd) \
+ (COLORREF)SNDMSGA((hwnd), TVM_GETTEXTCOLOR, 0, 0)
+
+#define TreeView_SetScrollTime(hwnd, uTime) \
+ (UINT)SNDMSGA((hwnd), TVM_SETSCROLLTIME, uTime, 0)
+
+#define TreeView_GetScrollTime(hwnd) \
+ (UINT)SNDMSGA((hwnd), TVM_GETSCROLLTIME, 0, 0)
+
+#define TreeView_SetInsertMark(hwnd, hItem, fAfter) \
+ (BOOL)SNDMSGA((hwnd), TVM_SETINSERTMARK, (WPARAM)(fAfter), \
+ (LPARAM) (hItem))
+
+#define TreeView_SetInsertMarkColor(hwnd, clr) \
+ (COLORREF)SNDMSGA((hwnd), TVM_SETINSERTMARKCOLOR, 0, (LPARAM)clr)
+
+#define TreeView_GetInsertMarkColor(hwnd) \
+ (COLORREF)SNDMSGA((hwnd), TVM_GETINSERTMARKCOLOR, 0, 0)
+
+#define TreeView_GetItemState(hwndTV, hti, mask) \
+ (UINT)SNDMSGA((hwndTV), TVM_GETITEMSTATE, (WPARAM)(hti), (LPARAM)(mask))
+#define TreeView_GetCheckState(hwndTV, hti) \
+ ((((UINT)(SNDMSGA((hwndTV), TVM_GETITEMSTATE, (WPARAM)(hti), \
+ TVIS_STATEIMAGEMASK))) >> 12) -1)
+
+#define TreeView_SetLineColor(hwnd, clr) \
+ (COLORREF)SNDMSGA((hwnd), TVM_SETLINECOLOR, 0, (LPARAM)(clr))
+
+#define TreeView_GetLineColor(hwnd) \
+ (COLORREF)SNDMSGA((hwnd), TVM_GETLINECOLOR, 0, 0)
+
+#define TreeView_SetItemState(hwndTV, hti, data, _mask) \
+{ TVITEM _TVi; \
+ _TVi.mask = TVIF_STATE; \
+ _TVi.hItem = hti; \
+ _TVi.stateMask = _mask; \
+ _TVi.state = data; \
+ SNDMSGA((hwndTV), TVM_SETITEM, 0, (LPARAM)(TV_ITEM *)&_TVi); \
+}
+
+
+/* Listview control */
+
+#define WC_LISTVIEWA "SysListView32"
+#if defined(__GNUC__)
+# define WC_LISTVIEWW (const WCHAR []){ 'S','y','s', \
+ 'L','i','s','t','V','i','e','w','3','2',0 }
+#elif defined(_MSC_VER)
+# define WC_LISTVIEWW L"SysListView32"
+#else
+static const WCHAR WC_LISTVIEWW[] = { 'S','y','s',
+ 'L','i','s','t','V','i','e','w','3','2',0 };
+#endif
+#define WC_LISTVIEW WINELIB_NAME_AW(WC_LISTVIEW)
+
+#define LVSCW_AUTOSIZE -1
+#define LVSCW_AUTOSIZE_USEHEADER -2
+
+#define LVS_ICON 0x0000
+#define LVS_REPORT 0x0001
+#define LVS_SMALLICON 0x0002
+#define LVS_LIST 0x0003
+#define LVS_TYPEMASK 0x0003
+#define LVS_SINGLESEL 0x0004
+#define LVS_SHOWSELALWAYS 0x0008
+#define LVS_SORTASCENDING 0x0010
+#define LVS_SORTDESCENDING 0x0020
+#define LVS_SHAREIMAGELISTS 0x0040
+#define LVS_NOLABELWRAP 0x0080
+#define LVS_AUTOARRANGE 0x0100
+#define LVS_EDITLABELS 0x0200
+#define LVS_OWNERDATA 0x1000
+#define LVS_NOSCROLL 0x2000
+#define LVS_TYPESTYLEMASK 0xfc00
+#define LVS_ALIGNTOP 0x0000
+#define LVS_ALIGNLEFT 0x0800
+#define LVS_ALIGNMASK 0x0c00
+#define LVS_OWNERDRAWFIXED 0x0400
+#define LVS_NOCOLUMNHEADER 0x4000
+#define LVS_NOSORTHEADER 0x8000
+
+#define LVS_EX_GRIDLINES 0x0001
+#define LVS_EX_SUBITEMIMAGES 0x0002
+#define LVS_EX_CHECKBOXES 0x0004
+#define LVS_EX_TRACKSELECT 0x0008
+#define LVS_EX_HEADERDRAGDROP 0x0010
+#define LVS_EX_FULLROWSELECT 0x0020
+#define LVS_EX_ONECLICKACTIVATE 0x0040
+#define LVS_EX_TWOCLICKACTIVATE 0x0080
+#define LVS_EX_FLATSB 0x0100
+#define LVS_EX_REGIONAL 0x0200
+#define LVS_EX_INFOTIP 0x0400
+#define LVS_EX_UNDERLINEHOT 0x0800
+#define LVS_EX_UNDERLINECOLD 0x1000
+#define LVS_EX_MULTIWORKAREAS 0x2000
+
+#define LVCF_FMT 0x0001
+#define LVCF_WIDTH 0x0002
+#define LVCF_TEXT 0x0004
+#define LVCF_SUBITEM 0x0008
+#define LVCF_IMAGE 0x0010
+#define LVCF_ORDER 0x0020
+
+#define LVCFMT_LEFT 0x0000
+#define LVCFMT_RIGHT 0x0001
+#define LVCFMT_CENTER 0x0002
+#define LVCFMT_JUSTIFYMASK 0x0003
+#define LVCFMT_IMAGE 0x0800
+#define LVCFMT_BITMAP_ON_RIGHT 0x1000
+#define LVCFMT_COL_HAS_IMAGES 0x8000
+
+#define LVSIL_NORMAL 0
+#define LVSIL_SMALL 1
+#define LVSIL_STATE 2
+
+/* following 2 flags only for LVS_OWNERDATA listviews */
+/* and only in report or list mode */
+#define LVSICF_NOINVALIDATEALL 0x0001
+#define LVSICF_NOSCROLL 0x0002
+
+
+#define LVFI_PARAM 0X0001
+#define LVFI_STRING 0X0002
+#define LVFI_PARTIAL 0X0008
+#define LVFI_WRAP 0X0020
+#define LVFI_NEARESTXY 0X0040
+
+#define LVIF_TEXT 0x0001
+#define LVIF_IMAGE 0x0002
+#define LVIF_PARAM 0x0004
+#define LVIF_STATE 0x0008
+#define LVIF_INDENT 0x0010
+#define LVIF_NORECOMPUTE 0x0800
+#define LVIF_DI_SETITEM 0x1000
+
+#define LVIR_BOUNDS 0x0000
+#define LVIR_LABEL 0x0002
+#define LVIR_ICON 0x0001
+#define LVIR_SELECTBOUNDS 0x0003
+
+#define LVIS_FOCUSED 0x0001
+#define LVIS_SELECTED 0x0002
+#define LVIS_CUT 0x0004
+#define LVIS_DROPHILITED 0x0008
+#define LVIS_ACTIVATING 0x0020
+
+#define LVIS_OVERLAYMASK 0x0F00
+#define LVIS_STATEIMAGEMASK 0xF000
+
+#define LVNI_ALL 0x0000
+#define LVNI_FOCUSED 0x0001
+#define LVNI_SELECTED 0x0002
+#define LVNI_CUT 0x0004
+#define LVNI_DROPHILITED 0x0008
+
+#define LVNI_ABOVE 0x0100
+#define LVNI_BELOW 0x0200
+#define LVNI_TOLEFT 0x0400
+#define LVNI_TORIGHT 0x0800
+
+#define LVHT_NOWHERE 0x0001
+#define LVHT_ONITEMICON 0x0002
+#define LVHT_ONITEMLABEL 0x0004
+#define LVHT_ONITEMSTATEICON 0x0008
+#define LVHT_ONITEM (LVHT_ONITEMICON|LVHT_ONITEMLABEL|LVHT_ONITEMSTATEICON)
+
+#define LVHT_ABOVE 0x0008
+#define LVHT_BELOW 0x0010
+#define LVHT_TORIGHT 0x0020
+#define LVHT_TOLEFT 0x0040
+
+#define LVM_FIRST 0x1000
+#define LVM_GETBKCOLOR (LVM_FIRST+0)
+#define LVM_SETBKCOLOR (LVM_FIRST+1)
+#define LVM_GETIMAGELIST (LVM_FIRST+2)
+#define LVM_SETIMAGELIST (LVM_FIRST+3)
+#define LVM_GETITEMCOUNT (LVM_FIRST+4)
+#define LVM_GETITEMA (LVM_FIRST+5)
+#define LVM_GETITEMW (LVM_FIRST+75)
+#define LVM_GETITEM WINELIB_NAME_AW(LVM_GETITEM)
+#define LVM_SETITEMA (LVM_FIRST+6)
+#define LVM_SETITEMW (LVM_FIRST+76)
+#define LVM_SETITEM WINELIB_NAME_AW(LVM_SETITEM)
+#define LVM_INSERTITEMA (LVM_FIRST+7)
+#define LVM_INSERTITEMW (LVM_FIRST+77)
+#define LVM_INSERTITEM WINELIB_NAME_AW(LVM_INSERTITEM)
+#define LVM_DELETEITEM (LVM_FIRST+8)
+#define LVM_DELETEALLITEMS (LVM_FIRST+9)
+#define LVM_GETCALLBACKMASK (LVM_FIRST+10)
+#define LVM_SETCALLBACKMASK (LVM_FIRST+11)
+#define LVM_GETNEXTITEM (LVM_FIRST+12)
+#define LVM_FINDITEMA (LVM_FIRST+13)
+#define LVM_FINDITEMW (LVM_FIRST+83)
+#define LVM_FINDITEM WINELIB_NAME_AW(LVM_FINDITEM)
+#define LVM_GETITEMRECT (LVM_FIRST+14)
+#define LVM_SETITEMPOSITION (LVM_FIRST+15)
+#define LVM_GETITEMPOSITION (LVM_FIRST+16)
+#define LVM_GETSTRINGWIDTHA (LVM_FIRST+17)
+#define LVM_GETSTRINGWIDTHW (LVM_FIRST+87)
+#define LVM_GETSTRINGWIDTH WINELIB_NAME_AW(LVM_GETSTRINGWIDTH)
+#define LVM_HITTEST (LVM_FIRST+18)
+#define LVM_ENSUREVISIBLE (LVM_FIRST+19)
+#define LVM_SCROLL (LVM_FIRST+20)
+#define LVM_REDRAWITEMS (LVM_FIRST+21)
+#define LVM_ARRANGE (LVM_FIRST+22)
+#define LVM_EDITLABELA (LVM_FIRST+23)
+#define LVM_EDITLABELW (LVM_FIRST+118)
+#define LVM_EDITLABEL WINELIB_NAME_AW(LVM_EDITLABEL)
+#define LVM_GETEDITCONTROL (LVM_FIRST+24)
+#define LVM_GETCOLUMNA (LVM_FIRST+25)
+#define LVM_GETCOLUMNW (LVM_FIRST+95)
+#define LVM_GETCOLUMN WINELIB_NAME_AW(LVM_GETCOLUMN)
+#define LVM_SETCOLUMNA (LVM_FIRST+26)
+#define LVM_SETCOLUMNW (LVM_FIRST+96)
+#define LVM_SETCOLUMN WINELIB_NAME_AW(LVM_SETCOLUMN)
+#define LVM_INSERTCOLUMNA (LVM_FIRST+27)
+#define LVM_INSERTCOLUMNW (LVM_FIRST+97)
+#define LVM_INSERTCOLUMN WINELIB_NAME_AW(LVM_INSERTCOLUMN)
+#define LVM_DELETECOLUMN (LVM_FIRST+28)
+#define LVM_GETCOLUMNWIDTH (LVM_FIRST+29)
+#define LVM_SETCOLUMNWIDTH (LVM_FIRST+30)
+#define LVM_GETHEADER (LVM_FIRST+31)
+
+#define LVM_CREATEDRAGIMAGE (LVM_FIRST+33)
+#define LVM_GETVIEWRECT (LVM_FIRST+34)
+#define LVM_GETTEXTCOLOR (LVM_FIRST+35)
+#define LVM_SETTEXTCOLOR (LVM_FIRST+36)
+#define LVM_GETTEXTBKCOLOR (LVM_FIRST+37)
+#define LVM_SETTEXTBKCOLOR (LVM_FIRST+38)
+#define LVM_GETTOPINDEX (LVM_FIRST+39)
+#define LVM_GETCOUNTPERPAGE (LVM_FIRST+40)
+#define LVM_GETORIGIN (LVM_FIRST+41)
+#define LVM_UPDATE (LVM_FIRST+42)
+#define LVM_SETITEMSTATE (LVM_FIRST+43)
+#define LVM_GETITEMSTATE (LVM_FIRST+44)
+#define LVM_GETITEMTEXTA (LVM_FIRST+45)
+#define LVM_GETITEMTEXTW (LVM_FIRST+115)
+#define LVM_GETITEMTEXT WINELIB_NAME_AW(LVM_GETITEMTEXT)
+#define LVM_SETITEMTEXTA (LVM_FIRST+46)
+#define LVM_SETITEMTEXTW (LVM_FIRST+116)
+#define LVM_SETITEMTEXT WINELIB_NAME_AW(LVM_SETITEMTEXT)
+#define LVM_SETITEMCOUNT (LVM_FIRST+47)
+#define LVM_SORTITEMS (LVM_FIRST+48)
+#define LVM_SETITEMPOSITION32 (LVM_FIRST+49)
+#define LVM_GETSELECTEDCOUNT (LVM_FIRST+50)
+#define LVM_GETITEMSPACING (LVM_FIRST+51)
+#define LVM_GETISEARCHSTRINGA (LVM_FIRST+52)
+#define LVM_GETISEARCHSTRINGW (LVM_FIRST+117)
+#define LVM_GETISEARCHSTRING WINELIB_NAME_AW(LVM_GETISEARCHSTRING)
+#define LVM_SETICONSPACING (LVM_FIRST+53)
+#define LVM_SETEXTENDEDLISTVIEWSTYLE (LVM_FIRST+54)
+#define LVM_GETEXTENDEDLISTVIEWSTYLE (LVM_FIRST+55)
+#define LVM_GETSUBITEMRECT (LVM_FIRST+56)
+#define LVM_SUBITEMHITTEST (LVM_FIRST+57)
+#define LVM_SETCOLUMNORDERARRAY (LVM_FIRST+58)
+#define LVM_GETCOLUMNORDERARRAY (LVM_FIRST+59)
+#define LVM_SETHOTITEM (LVM_FIRST+60)
+#define LVM_GETHOTITEM (LVM_FIRST+61)
+#define LVM_SETHOTCURSOR (LVM_FIRST+62)
+#define LVM_GETHOTCURSOR (LVM_FIRST+63)
+#define LVM_APPROXIMATEVIEWRECT (LVM_FIRST+64)
+#define LVM_SETWORKAREAS (LVM_FIRST+65)
+#define LVM_GETSELECTIONMARK (LVM_FIRST+66)
+#define LVM_SETSELECTIONMARK (LVM_FIRST+67)
+#define LVM_SETBKIMAGEA (LVM_FIRST+68)
+#define LVM_SETBKIMAGEW (LVM_FIRST+138)
+#define LVM_SETBKIMAGE WINELIB_NAME_AW(LVM_SETBKIMAGE)
+#define LVM_GETBKIMAGEA (LVM_FIRST+69)
+#define LVM_GETBKIMAGEW (LVM_FIRST+139)
+#define LVM_GETBKIMAGE WINELIB_NAME_AW(LVM_GETBKIMAGE)
+#define LVM_GETWORKAREAS (LVM_FIRST+70)
+#define LVM_SETHOVERTIME (LVM_FIRST+71)
+#define LVM_GETHOVERTIME (LVM_FIRST+72)
+#define LVM_GETNUMBEROFWORKAREAS (LVM_FIRST+73)
+#define LVM_SETTOOLTIPS (LVM_FIRST+74)
+#define LVM_GETTOOLTIPS (LVM_FIRST+78)
+#define LVM_GETUNICODEFORMAT (CCM_GETUNICODEFORMAT)
+#define LVM_SETUNICODEFORMAT (CCM_SETUNICODEFORMAT)
+
+#define LVN_FIRST (0U-100U)
+#define LVN_LAST (0U-199U)
+#define LVN_ITEMCHANGING (LVN_FIRST-0)
+#define LVN_ITEMCHANGED (LVN_FIRST-1)
+#define LVN_INSERTITEM (LVN_FIRST-2)
+#define LVN_DELETEITEM (LVN_FIRST-3)
+#define LVN_DELETEALLITEMS (LVN_FIRST-4)
+#define LVN_BEGINLABELEDITA (LVN_FIRST-5)
+#define LVN_BEGINLABELEDITW (LVN_FIRST-75)
+#define LVN_BEGINLABELEDIT WINELIB_NAME_AW(LVN_BEGINLABELEDIT)
+#define LVN_ENDLABELEDITA (LVN_FIRST-6)
+#define LVN_ENDLABELEDITW (LVN_FIRST-76)
+#define LVN_ENDLABELEDIT WINELIB_NAME_AW(LVN_ENDLABELEDIT)
+#define LVN_COLUMNCLICK (LVN_FIRST-8)
+#define LVN_BEGINDRAG (LVN_FIRST-9)
+#define LVN_BEGINRDRAG (LVN_FIRST-11)
+#define LVN_ODCACHEHINT (LVN_FIRST-13)
+#define LVN_ITEMACTIVATE (LVN_FIRST-14)
+#define LVN_ODSTATECHANGED (LVN_FIRST-15)
+#define LVN_HOTTRACK (LVN_FIRST-21)
+#define LVN_ODFINDITEMA (LVN_FIRST-52)
+#define LVN_ODFINDITEMW (LVN_FIRST-79)
+#define LVN_ODFINDITEM WINELIB_NAME_AW(LVN_ODFINDITEM)
+#define LVN_GETDISPINFOA (LVN_FIRST-50)
+#define LVN_GETDISPINFOW (LVN_FIRST-77)
+#define LVN_GETDISPINFO WINELIB_NAME_AW(LVN_GETDISPINFO)
+#define LVN_SETDISPINFOA (LVN_FIRST-51)
+#define LVN_SETDISPINFOW (LVN_FIRST-78)
+#define LVN_SETDISPINFO WINELIB_NAME_AW(LVN_SETDISPINFO)
+#define LVN_KEYDOWN (LVN_FIRST-55)
+#define LVN_MARQUEEBEGIN (LVN_FIRST-56)
+#define LVN_GETINFOTIPA (LVN_FIRST-57)
+#define LVN_GETINFOTIPW (LVN_FIRST-58)
+#define LVN_GETINFOTIP WINELIB_NAME_AW(LVN_GETINFOTIP)
+
+#define LVA_ALIGNLEFT 0x0000
+#define LVA_DEFAULT 0x0001
+#define LVA_ALIGNTOP 0x0002
+#define LVA_SNAPTOGRID 0x0005
+
+typedef struct tagLVITEMA
+{
+ UINT mask;
+ INT iItem;
+ INT iSubItem;
+ UINT state;
+ UINT stateMask;
+ LPSTR pszText;
+ INT cchTextMax;
+ INT iImage;
+ LPARAM lParam;
+ INT iIndent; /* (_WIN32_IE >= 0x0300) */
+ int iGroupId; /* (_WIN32_IE >= 0x560) */
+ UINT cColumns; /* (_WIN32_IE >= 0x560) */
+ PUINT puColumns; /* (_WIN32_IE >= 0x560) */
+} LVITEMA, *LPLVITEMA;
+
+typedef struct tagLVITEMW
+{
+ UINT mask;
+ INT iItem;
+ INT iSubItem;
+ UINT state;
+ UINT stateMask;
+ LPWSTR pszText;
+ INT cchTextMax;
+ INT iImage;
+ LPARAM lParam;
+ INT iIndent; /* (_WIN32_IE >= 0x0300) */
+ int iGroupId; /* (_WIN32_IE >= 0x560) */
+ UINT cColumns; /* (_WIN32_IE >= 0x560) */
+ PUINT puColumns; /* (_WIN32_IE >= 0x560) */
+} LVITEMW, *LPLVITEMW;
+
+#define LVITEM WINELIB_NAME_AW(LVITEM)
+#define LPLVITEM WINELIB_NAME_AW(LPLVITEM)
+
+#define LVITEM_V1_SIZEA CCSIZEOF_STRUCT(LVITEMA, lParam)
+#define LVITEM_V1_SIZEW CCSIZEOF_STRUCT(LVITEMW, lParam)
+#define LVITEM_V1_SIZE WINELIB_NAME_AW(LVITEM_V1_SIZE)
+
+#define LV_ITEM LVITEM
+
+typedef struct LVSETINFOTIPA
+{
+ UINT cbSize;
+ DWORD dwFlags;
+ LPSTR pszText;
+ int iItem;
+ int iSubItem;
+} LVSETINFOTIPA, *PLVSETINFOTIPA;
+
+typedef struct LVSETINFOTIPW
+{
+ UINT cbSize;
+ DWORD dwFlags;
+ LPWSTR pszText;
+ int iItem;
+ int iSubItem;
+} LVSETINFOTIPW, *PLVSETINFOTIPW;
+
+#define LVSETINFOTIP WINELIB_NAME_AW(LVSETINFOTIP)
+#define PLVSETINFOTIP WINELIB_NAME_AW(PLVSETINFOTIP)
+
+/* ListView background image structs and constants
+ For _WIN32_IE version 0x400 and later. */
+
+typedef struct tagLVBKIMAGEA
+{
+ ULONG ulFlags;
+ HBITMAP hbm;
+ LPSTR pszImage;
+ UINT cchImageMax;
+ int xOffsetPercent;
+ int yOffsetPercent;
+} LVBKIMAGEA, *LPLVBKIMAGEA;
+
+typedef struct tagLVBKIMAGEW
+{
+ ULONG ulFlags;
+ HBITMAP hbm;
+ LPWSTR pszImage;
+ UINT cchImageMax;
+ int xOffsetPercent;
+ int yOffsetPercent;
+} LVBKIMAGEW, *LPLVBKIMAGEW;
+
+#define LVBKIMAGE WINELIB_NAME_AW(LVBKIMAGE)
+#define LPLVBKIMAGE WINELIB_NAME_AW(LPLVBKIMAGE)
+
+#define LVBKIF_SOURCE_NONE 0x00000000
+#define LVBKIF_SOURCE_HBITMAP 0x00000001
+#define LVBKIF_SOURCE_URL 0x00000002
+#define LVBKIF_SOURCE_MASK 0x00000003
+#define LVBKIF_STYLE_NORMAL 0x00000000
+#define LVBKIF_STYLE_TILE 0x00000010
+#define LVBKIF_STYLE_MASK 0x00000010
+
+#define ListView_SetBkImage(hwnd, plvbki) \
+ (BOOL)SNDMSG((hwnd), LVM_SETBKIMAGE, 0, (LPARAM)plvbki)
+
+#define ListView_GetBkImage(hwnd, plvbki) \
+ (BOOL)SNDMSG((hwnd), LVM_GETBKIMAGE, 0, (LPARAM)plvbki)
+
+typedef struct tagLVCOLUMNA
+{
+ UINT mask;
+ INT fmt;
+ INT cx;
+ LPSTR pszText;
+ INT cchTextMax;
+ INT iSubItem;
+ INT iImage; /* (_WIN32_IE >= 0x0300) */
+ INT iOrder; /* (_WIN32_IE >= 0x0300) */
+} LVCOLUMNA, *LPLVCOLUMNA;
+
+typedef struct tagLVCOLUMNW
+{
+ UINT mask;
+ INT fmt;
+ INT cx;
+ LPWSTR pszText;
+ INT cchTextMax;
+ INT iSubItem;
+ INT iImage; /* (_WIN32_IE >= 0x0300) */
+ INT iOrder; /* (_WIN32_IE >= 0x0300) */
+} LVCOLUMNW, *LPLVCOLUMNW;
+
+#define LVCOLUMN WINELIB_NAME_AW(LVCOLUMN)
+#define LPLVCOLUMN WINELIB_NAME_AW(LPLVCOLUMN)
+
+#define LVCOLUMN_V1_SIZEA CCSIZEOF_STRUCT(LVCOLUMNA, iSubItem)
+#define LVCOLUMN_V1_SIZEW CCSIZEOF_STRUCT(LVCOLUMNW, iSubItem)
+#define LVCOLUMN_V1_SIZE WINELIB_NAME_AW(LVCOLUMN_V1_SIZE)
+
+#define LV_COLUMN LVCOLUMN
+
+
+typedef struct tagNMLISTVIEW
+{
+ NMHDR hdr;
+ INT iItem;
+ INT iSubItem;
+ UINT uNewState;
+ UINT uOldState;
+ UINT uChanged;
+ POINT ptAction;
+ LPARAM lParam;
+} NMLISTVIEW, *LPNMLISTVIEW;
+
+#define NM_LISTVIEW NMLISTVIEW
+#define LPNM_LISTVIEW LPNMLISTVIEW
+
+typedef struct tagNMITEMACTIVATE
+{
+ NMHDR hdr;
+ int iItem;
+ int iSubItem;
+ UINT uNewState;
+ UINT uOldState;
+ UINT uChanged;
+ POINT ptAction;
+ LPARAM lParam;
+ UINT uKeyFlags;
+} NMITEMACTIVATE, *LPNMITEMACTIVATE;
+
+typedef struct tagLVDISPINFOA
+{
+ NMHDR hdr;
+ LVITEMA item;
+} NMLVDISPINFOA, *LPNMLVDISPINFOA;
+
+typedef struct tagLVDISPINFOW
+{
+ NMHDR hdr;
+ LVITEMW item;
+} NMLVDISPINFOW, *LPNMLVDISPINFOW;
+
+#define NMLVDISPINFO WINELIB_NAME_AW(NMLVDISPINFO)
+#define LPNMLVDISPINFO WINELIB_NAME_AW(LPNMLVDISPINFO)
+
+#define LV_DISPINFO NMLVDISPINFO
+
+#include "pshpack1.h"
+typedef struct tagLVKEYDOWN
+{
+ NMHDR hdr;
+ WORD wVKey;
+ UINT flags;
+} NMLVKEYDOWN, *LPNMLVKEYDOWN;
+#include "poppack.h"
+
+#define LV_KEYDOWN NMLVKEYDOWN
+
+typedef struct tagNMLVGETINFOTIPA
+{
+ NMHDR hdr;
+ DWORD dwFlags;
+ LPSTR pszText;
+ int cchTextMax;
+ int iItem;
+ int iSubItem;
+ LPARAM lParam;
+} NMLVGETINFOTIPA, *LPNMLVGETINFOTIPA;
+
+typedef struct tagNMLVGETINFOTIPW
+{
+ NMHDR hdr;
+ DWORD dwFlags;
+ LPWSTR pszText;
+ int cchTextMax;
+ int iItem;
+ int iSubItem;
+ LPARAM lParam;
+} NMLVGETINFOTIPW, *LPNMLVGETINFOTIPW;
+
+#define NMLVGETINFOTIP WINELIB_NAME_AW(NMLVGETINFOTIP)
+#define LPNMLVGETINFOTIP WINELIB_NAME_AW(LPNMLVGETINFOTIP)
+
+typedef struct tagLVHITTESTINFO
+{
+ POINT pt;
+ UINT flags;
+ INT iItem;
+ INT iSubItem;
+} LVHITTESTINFO, *LPLVHITTESTINFO;
+
+#define LV_HITTESTINFO LVHITTESTINFO
+#define _LV_HITTESTINFO tagLVHITTESTINFO
+#define LVHITTESTINFO_V1_SIZE CCSIZEOF_STRUCT(LVHITTESTINFO,iItem)
+
+typedef struct tagLVFINDINFOA
+{
+ UINT flags;
+ LPCSTR psz;
+ LPARAM lParam;
+ POINT pt;
+ UINT vkDirection;
+} LVFINDINFOA, *LPLVFINDINFOA;
+
+typedef struct tagLVFINDINFOW
+{
+ UINT flags;
+ LPCWSTR psz;
+ LPARAM lParam;
+ POINT pt;
+ UINT vkDirection;
+} LVFINDINFOW, *LPLVFINDINFOW;
+
+#define LVFINDINFO WINELIB_NAME_AW(LVFINDINFO)
+#define LPLVFINDINFO WINELIB_NAME_AW(LPLVFINDINFO)
+
+/* Groups relates structures */
+
+typedef struct LVGROUPA
+{
+ UINT cbSize;
+ UINT mask;
+ LPSTR pszHeader;
+ int cchHeader;
+ int iGroupId;
+ UINT stateMask;
+ UINT state;
+ UINT uAlign;
+} LVGROUPA, *PLVGROUPA;
+
+typedef struct LVGROUPW
+{
+ UINT cbSize;
+ UINT mask;
+ LPWSTR pszHeader;
+ int cchHeader;
+ int iGroupId;
+ UINT stateMask;
+ UINT state;
+ UINT uAlign;
+} LVGROUPW, *PLVGROUPW;
+
+#define LVGROUP WINELIB_NAME_AW(LVGROUP)
+#define PLVGROUP WINELIB_NAME_AW(PLVGROUP)
+
+typedef struct LVGROUPMETRICS
+{
+ UINT cbSize;
+ UINT mask;
+ UINT Left;
+ UINT Top;
+ UINT Right;
+ UINT Bottom;
+ COLORREF crLeft;
+ COLORREF crTop;
+ COLORREF crRight;
+ COLORREF crBottom;
+ COLORREF crRightHeader;
+ COLORREF crFooter;
+} LVGROUPMETRICS, *PLVGROUPMETRICS;
+
+typedef INT (*PFNLVGROUPCOMPARE)(INT, INT, VOID*);
+
+typedef struct LVINSERTGROUPSORTEDA
+{
+ PFNLVGROUPCOMPARE pfnGroupCompare;
+ LPVOID *pvData;
+ LVGROUPA lvGroup;
+} LVINSERTGROUPSORTEDA, *PLVINSERTGROUPSORTEDA;
+
+typedef struct LVINSERTGROUPSORTEDW
+{
+ PFNLVGROUPCOMPARE pfnGroupCompare;
+ LPVOID *pvData;
+ LVGROUPW lvGroup;
+} LVINSERTGROUPSORTEDW, *PLVINSERTGROUPSORTEDW;
+
+#define LVINSERTGROUPSORTED WINELIB_NAME_AW(LVINSERTGROUPSORTED)
+#define PLVINSERTGROUPSORTED WINELIB_NAME_AW(PLVINSERTGROUPSORTED)
+
+/* Tile related structures */
+
+typedef struct LVTILEINFO
+{
+ UINT cbSize;
+ int iItem;
+ UINT cColumns;
+ PUINT puColumns;
+} LVTILEINFO, *PLVTILEINFO;
+
+typedef struct LVTILEVIEWINFO
+{
+ UINT cbSize;
+ DWORD dwMask;
+ DWORD dwFlags;
+ SIZE sizeTile;
+ int cLines;
+ RECT rcLabelMargin;
+} LVTILEVIEWINFO, *PLVTILEVIEWINFO;
+
+typedef struct LVINSERTMARK
+{
+ UINT cbSize;
+ DWORD dwFlags;
+ int iItem;
+ DWORD dwReserved;
+} LVINSERTMARK, *PLVINSERTMARK;
+
+typedef struct tagTCHITTESTINFO
+{
+ POINT pt;
+ UINT flags;
+} TCHITTESTINFO, *LPTCHITTESTINFO;
+
+#define TC_HITTESTINFO TCHITTESTINFO
+
+typedef INT (CALLBACK *PFNLVCOMPARE)(LPARAM, LPARAM, LPARAM);
+
+#define NMLVCUSTOMDRAW_V3_SIZE CCSIZEOF_STRUCT(NMLCUSTOMDRW, clrTextBk)
+
+typedef struct tagNMLVCUSTOMDRAW
+{
+ NMCUSTOMDRAW nmcd;
+ COLORREF clrText;
+ COLORREF clrTextBk;
+ int iSubItem; /* (_WIN32_IE >= 0x0400) */
+ DWORD dwItemType; /* (_WIN32_IE >= 0x560) */
+ COLORREF clrFace; /* (_WIN32_IE >= 0x560) */
+ int iIconEffect; /* (_WIN32_IE >= 0x560) */
+ int iIconPhase; /* (_WIN32_IE >= 0x560) */
+ int iPartId; /* (_WIN32_IE >= 0x560) */
+ int iStateId; /* (_WIN32_IE >= 0x560) */
+ RECT rcText; /* (_WIN32_IE >= 0x560) */
+ UINT uAlign; /* (_WIN32_IE >= 0x560) */
+} NMLVCUSTOMDRAW, *LPNMLVCUSTOMDRAW;
+
+typedef struct tagNMLVCACHEHINT
+{
+ NMHDR hdr;
+ INT iFrom;
+ INT iTo;
+} NMLVCACHEHINT, *LPNMLVCACHEHINT;
+
+#define LPNM_CACHEHINT LPNMLVCACHEHINT
+#define PNM_CACHEHINT LPNMLVCACHEHINT
+#define NM_CACHEHINT NMLVCACHEHINT
+
+typedef struct tagNMLVFINDITEMA
+{
+ NMHDR hdr;
+ int iStart;
+ LVFINDINFOA lvfi;
+} NMLVFINDITEMA, *LPNMLVFINDITEMA;
+
+typedef struct tagNMLVFINDITEMW
+{
+ NMHDR hdr;
+ int iStart;
+ LVFINDINFOW lvfi;
+} NMLVFINDITEMW, *LPNMLVFINDITEMW;
+
+#define NMLVFINDITEM WINELIB_NAME_AW(NMLVFINDITEM)
+#define LPNMLVFINDITEM WINELIB_NAME_AW(LPNMLVFINDITEM)
+#define NM_FINDITEM NMLVFINDITEM
+#define LPNM_FINDITEM LPNMLVFINDITEM
+#define PNM_FINDITEM LPNMLVFINDITEM
+
+typedef struct tagNMLVODSTATECHANGE
+{
+ NMHDR hdr;
+ int iFrom;
+ int iTo;
+ UINT uNewState;
+ UINT uOldState;
+} NMLVODSTATECHANGE, *LPNMLVODSTATECHANGE;
+
+#define PNM_ODSTATECHANGE LPNMLVODSTATECHANGE
+#define LPNM_ODSTATECHANGE LPNMLVODSTATECHANGE
+#define NM_ODSTATECHANGE NMLVODSTATECHANGE
+
+typedef struct NMLVSCROLL
+{
+ NMHDR hdr;
+ int dx;
+ int dy;
+} NMLVSCROLL, *LPNMLVSCROLL;
+
+#define ListView_SetTextBkColor(hwnd,clrBk) \
+ (BOOL)SNDMSGA((hwnd),LVM_SETTEXTBKCOLOR,0,(LPARAM)(COLORREF)(clrBk))
+#define ListView_SetTextColor(hwnd,clrBk) \
+ (BOOL)SNDMSGA((hwnd),LVM_SETTEXTCOLOR,0,(LPARAM)(COLORREF)(clrBk))
+#define ListView_DeleteColumn(hwnd,col)\
+ (LRESULT)SNDMSGA((hwnd),LVM_DELETECOLUMN,0,(LPARAM)(INT)(col))
+#define ListView_GetColumnA(hwnd,x,col)\
+ (LRESULT)SNDMSGA((hwnd),LVM_GETCOLUMNA,(WPARAM)(INT)(x),(LPARAM)(LPLVCOLUMNA)(col))
+#define ListView_GetColumnW(hwnd,x,col)\
+ (LRESULT)SNDMSGW((hwnd),LVM_GETCOLUMNW,(WPARAM)(INT)(x),(LPARAM)(LPLVCOLUMNW)(col))
+#define ListView_GetColumn WINELIB_NAME_AW(ListView_GetColumn)
+#define ListView_SetColumnA(hwnd,x,col)\
+ (LRESULT)SNDMSGA((hwnd),LVM_SETCOLUMNA,(WPARAM)(INT)(x),(LPARAM)(LPLVCOLUMNA)(col))
+#define ListView_SetColumnW(hwnd,x,col)\
+ (LRESULT)SNDMSGW((hwnd),LVM_SETCOLUMNW,(WPARAM)(INT)(x),(LPARAM)(LPLVCOLUMNW)(col))
+#define ListView_SetColumn WINELIB_NAME_AW(ListView_SetColumn)
+
+
+#define ListView_GetNextItem(hwnd,nItem,flags) \
+ (INT)SNDMSGA((hwnd),LVM_GETNEXTITEM,(WPARAM)(INT)(nItem),(LPARAM)(MAKELPARAM(flags,0)))
+#define ListView_FindItemA(hwnd,nItem,plvfi) \
+ (INT)SNDMSGA((hwnd),LVM_FINDITEMA,(WPARAM)(INT)(nItem),(LPARAM)(LVFINDINFOA*)(plvfi))
+#define ListView_FindItemW(hwnd,nItem,plvfi) \
+ (INT)SNDMSGW((hwnd),LVM_FINDITEMW,(WPARAM)(INT)(nItem),(LPARAM)(LVFINDINFOW*)(plvfi))
+#define ListView_FindItem WINELIB_NAME_AW(ListView_FindItem)
+
+#define ListView_Arrange(hwnd,code) \
+ (INT)SNDMSGA((hwnd),LVM_ARRANGE,(WPARAM)(INT)(code),0L)
+#define ListView_GetItemPosition(hwnd,i,ppt) \
+ (INT)SNDMSGA((hwnd),LVM_GETITEMPOSITION,(WPARAM)(INT)(i),(LPARAM)(LPPOINT)(ppt))
+#define ListView_GetItemRect(hwnd,i,prc,code) \
+ (BOOL)SNDMSGA((hwnd), LVM_GETITEMRECT, (WPARAM)(int)(i), \
+ ((prc) ? (((RECT*)(prc))->left = (code),(LPARAM)(RECT \
+ *)(prc)) : (LPARAM)(RECT*)NULL))
+#define ListView_SetItemA(hwnd,pitem) \
+ (INT)SNDMSGA((hwnd),LVM_SETITEMA,0,(LPARAM)(const LVITEMA *)(pitem))
+#define ListView_SetItemW(hwnd,pitem) \
+ (INT)SNDMSGW((hwnd),LVM_SETITEMW,0,(LPARAM)(const LVITEMW *)(pitem))
+#define ListView_SetItem WINELIB_NAME_AW(ListView_SetItem)
+#define ListView_SetItemState(hwnd,i,pitem) \
+ (BOOL)SNDMSGA((hwnd),LVM_SETITEMSTATE,(WPARAM)(UINT)(i),(LPARAM)(LPLVITEMA)(pitem))
+#define ListView_GetItemState(hwnd,i,mask) \
+ (BOOL)SNDMSGA((hwnd),LVM_GETITEMSTATE,(WPARAM)(UINT)(i),(LPARAM)(UINT)(mask))
+#define ListView_GetCountPerPage(hwnd) \
+ (BOOL)SNDMSGW((hwnd),LVM_GETCOUNTPERPAGE,0,0L)
+#define ListView_GetImageList(hwnd,iImageList) \
+ (HIMAGELIST)SNDMSGA((hwnd),LVM_GETIMAGELIST,(WPARAM)(INT)(iImageList),0L)
+#define ListView_GetStringWidthA(hwnd,pstr) \
+ (INT)SNDMSGA((hwnd),LVM_GETSTRINGWIDTHA,0,(LPARAM)(LPCSTR)(pstr))
+#define ListView_GetStringWidthW(hwnd,pstr) \
+ (INT)SNDMSGW((hwnd),LVM_GETSTRINGWIDTHW,0,(LPARAM)(LPCWSTR)(pstr))
+#define ListView_GetStringWidth WINELIB_NAME_AW(ListView_GetStringWidth)
+#define ListView_GetTopIndex(hwnd) \
+ (BOOL)SNDMSGA((hwnd),LVM_GETTOPINDEX,0,0L)
+#define ListView_Scroll(hwnd,dx,dy) \
+ (BOOL)SNDMSGA((hwnd),LVM_SCROLL,(WPARAM)(INT)(dx),(LPARAM)(INT)(dy))
+#define ListView_EnsureVisible(hwnd,i,fPartialOk) \
+ (BOOL)SNDMSGA((hwnd),LVM_ENSUREVISIBLE,(WPARAM)(INT)i,(LPARAM)(BOOL)fPartialOk)
+#define ListView_SetBkColor(hwnd,clrBk) \
+ (BOOL)SNDMSGA((hwnd),LVM_SETBKCOLOR,0,(LPARAM)(COLORREF)(clrBk))
+#define ListView_SetImageList(hwnd,himl,iImageList) \
+ (HIMAGELIST)(UINT)SNDMSGA((hwnd),LVM_SETIMAGELIST,(WPARAM)(iImageList),(LPARAM)(UINT)(HIMAGELIST)(himl))
+#define ListView_GetItemCount(hwnd) \
+ (INT)SNDMSGA((hwnd),LVM_GETITEMCOUNT,0,0L)
+
+#define ListView_GetItemA(hwnd,pitem) \
+ (BOOL)SNDMSGA((hwnd),LVM_GETITEMA,0,(LPARAM)(LVITEMA *)(pitem))
+#define ListView_GetItemW(hwnd,pitem) \
+ (BOOL)SNDMSGW((hwnd),LVM_GETITEMW,0,(LPARAM)(LVITEMW *)(pitem))
+#define ListView_GetItem WINELIB_NAME_AW(ListView_GetItem)
+
+#define ListView_HitTest(hwnd,pinfo) \
+ (INT)SNDMSGA((hwnd),LVM_HITTEST,0,(LPARAM)(LPLVHITTESTINFO)(pinfo))
+
+#define ListView_InsertItemA(hwnd,pitem) \
+ (INT)SNDMSGA((hwnd),LVM_INSERTITEMA,0,(LPARAM)(const LVITEMA *)(pitem))
+#define ListView_InsertItemW(hwnd,pitem) \
+ (INT)SNDMSGW((hwnd),LVM_INSERTITEMW,0,(LPARAM)(const LVITEMW *)(pitem))
+#define ListView_InsertItem WINELIB_NAME_AW(ListView_InsertItem)
+
+#define ListView_DeleteAllItems(hwnd) \
+ (BOOL)SNDMSGA((hwnd),LVM_DELETEALLITEMS,0,0L)
+
+#define ListView_InsertColumnA(hwnd,iCol,pcol) \
+ (INT)SNDMSGA((hwnd),LVM_INSERTCOLUMNA,(WPARAM)(INT)(iCol),(LPARAM)(const LVCOLUMNA *)(pcol))
+#define ListView_InsertColumnW(hwnd,iCol,pcol) \
+ (INT)SNDMSGW((hwnd),LVM_INSERTCOLUMNW,(WPARAM)(INT)(iCol),(LPARAM)(const LVCOLUMNW *)(pcol))
+#define ListView_InsertColumn WINELIB_NAME_AW(ListView_InsertColumn)
+
+#define ListView_SortItems(hwndLV,_pfnCompare,_lPrm) \
+ (BOOL)SNDMSGA((hwndLV),LVM_SORTITEMS,(WPARAM)(LPARAM)_lPrm,(LPARAM)(PFNLVCOMPARE)_pfnCompare)
+#define ListView_SetItemPosition(hwndLV, i, x, y) \
+ (BOOL)SNDMSGA((hwndLV),LVM_SETITEMPOSITION,(WPARAM)(INT)(i),MAKELPARAM((x),(y)))
+#define ListView_GetSelectedCount(hwndLV) \
+ (UINT)SNDMSGA((hwndLV),LVM_GETSELECTEDCOUNT,0,0L)
+
+#define ListView_EditLabelA(hwndLV, i) \
+ (HWND)SNDMSGA((hwndLV),LVM_EDITLABELA,(WPARAM)(int)(i), 0L)
+#define ListView_EditLabelW(hwndLV, i) \
+ (HWND)SNDMSGW((hwndLV),LVM_EDITLABELW,(WPARAM)(int)(i), 0L)
+#define ListView_EditLabel WINELIB_NAME_AW(ListView_EditLabel)
+
+#define ListView_SetItemTextA(hwndLV, i, _iSubItem, _pszText) \
+{ LVITEMA _LVi; _LVi.iSubItem = _iSubItem; _LVi.pszText = _pszText;\
+ SNDMSGA(hwndLV, LVM_SETITEMTEXTA, (WPARAM)i, (LPARAM) (LVITEMA*)&_LVi);}
+#define ListView_SetItemTextW(hwndLV, i, _iSubItem, _pszText) \
+{ LVITEMW _LVi; _LVi.iSubItem = _iSubItem; _LVi.pszText = _pszText;\
+ SNDMSGW(hwndLV, LVM_SETITEMTEXTW, (WPARAM)i, (LPARAM) (LVITEMW*)& _LVi);}
+#define ListView_SetItemText WINELIB_NAME_AW(ListView_SetItemText)
+
+#define ListView_DeleteItem(hwndLV, i) \
+ (BOOL)SNDMSGA(hwndLV, LVM_DELETEITEM, (WPARAM)(int)(i), 0L)
+#define ListView_Update(hwndLV, i) \
+ (BOOL)SNDMSGA((hwndLV), LVM_UPDATE, (WPARAM)(i), 0L)
+#define ListView_GetColumnOrderArray(hwndLV, iCount, pi) \
+ (BOOL)SNDMSGA((hwndLV), LVM_GETCOLUMNORDERARRAY, (WPARAM)iCount, (LPARAM)(LPINT)pi)
+#define ListView_GetExtendedListViewStyle(hwndLV) \
+ (DWORD)SNDMSGA((hwndLV), LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0L)
+#define ListView_GetHotCursor(hwndLV) \
+ (HCURSOR)SNDMSGA((hwndLV), LVM_GETHOTCURSOR, 0, 0L)
+#define ListView_GetHotItem(hwndLV) \
+ (int)SNDMSGA((hwndLV), LVM_GETHOTITEM, 0, 0L)
+#define ListView_GetItemSpacing(hwndLV, fSmall) \
+ (DWORD)SNDMSGA((hwndLV), LVM_GETITEMSPACING, (WPARAM)fSmall, 0L)
+#define ListView_GetSubItemRect(hwndLV, iItem, iSubItem, code, prc) \
+ (BOOL)SNDMSGA((hwndLV), LVM_GETSUBITEMRECT, (WPARAM)(int)(iItem), \
+ ((prc) ? (((LPRECT)(prc))->top = iSubItem), (((LPRECT)(prc))->left = code):0), (LPARAM)prc)
+#define ListView_GetToolTips(hwndLV) \
+ (HWND)SNDMSGA((hwndLV), LVM_GETTOOLTIPS, 0, 0L)
+#define ListView_SetColumnOrderArray(hwndLV, iCount, pi) \
+ (BOOL)SNDMSGA((hwndLV), LVM_SETCOLUMNORDERARRAY, (WPARAM)iCount, (LPARAM)(LPINT)pi)
+#define ListView_SetExtendedListViewStyle(hwndLV, dw) \
+ (DWORD)SNDMSGA((hwndLV), LVM_SETEXTENDEDLISTVIEWSTYLE, 0, (LPARAM)dw)
+#define ListView_SetExtendedListViewStyleEx(hwndLV, dwMask, dw) \
+ (DWORD)SNDMSGA((hwndLV), LVM_SETEXTENDEDLISTVIEWSTYLE, (WPARAM)dwMask, (LPARAM)dw)
+#define ListView_SetHotCursor(hwndLV, hcur) \
+ (HCURSOR)SNDMSGA((hwndLV), LVM_SETHOTCURSOR, 0, (LPARAM)hcur)
+#define ListView_SetHotItem(hwndLV, i) \
+ (int)SNDMSGA((hwndLV), LVM_SETHOTITEM, (WPARAM)i, 0L)
+#define ListView_SetIconSpacing(hwndLV, cx, cy) \
+ (DWORD)SNDMSGA((hwndLV), LVM_SETICONSPACING, 0, MAKELONG(cx,cy))
+#define ListView_SetToolTips(hwndLV, hwndNewHwnd) \
+ (HWND)SNDMSGA((hwndLV), LVM_SETTOOLTIPS, (WPARAM)hwndNewHwnd, 0L)
+#define ListView_SubItemHitTest(hwndLV, plvhti) \
+ (int)SNDMSGA((hwndLV), LVM_SUBITEMHITTEST, 0, (LPARAM)(LPLVHITTESTINFO)(plvhti))
+
+
+/* Tab Control */
+
+#define WC_TABCONTROL16 "SysTabControl"
+#define WC_TABCONTROLA "SysTabControl32"
+#if defined(__GNUC__)
+# define WC_TABCONTROLW (const WCHAR []){ 'S','y','s', \
+ 'T','a','b','C','o','n','t','r','o','l','3','2',0 }
+#elif defined(_MSC_VER)
+# define WC_TABCONTROLW L"SysTabControl32"
+#else
+static const WCHAR WC_TABCONTROLW[] = { 'S','y','s',
+ 'T','a','b','C','o','n','t','r','o','l','3','2',0 };
+#endif
+#define WC_TABCONTROL WINELIB_NAME_AW(WC_TABCONTROL)
+
+/* tab control styles */
+#define TCS_SCROLLOPPOSITE 0x0001 /* assumes multiline tab */
+#define TCS_BOTTOM 0x0002
+#define TCS_RIGHT 0x0002
+#define TCS_MULTISELECT 0x0004 /* allow multi-select in button mode */
+#define TCS_FLATBUTTONS 0x0008
+#define TCS_FORCEICONLEFT 0x0010
+#define TCS_FORCELABELLEFT 0x0020
+#define TCS_HOTTRACK 0x0040
+#define TCS_VERTICAL 0x0080
+#define TCS_TABS 0x0000
+#define TCS_BUTTONS 0x0100
+#define TCS_SINGLELINE 0x0000
+#define TCS_MULTILINE 0x0200
+#define TCS_RIGHTJUSTIFY 0x0000
+#define TCS_FIXEDWIDTH 0x0400
+#define TCS_RAGGEDRIGHT 0x0800
+#define TCS_FOCUSONBUTTONDOWN 0x1000
+#define TCS_OWNERDRAWFIXED 0x2000
+#define TCS_TOOLTIPS 0x4000
+#define TCS_FOCUSNEVER 0x8000
+#define TCS_EX_FLATSEPARATORS 0x00000001 /* to be used with */
+#define TCS_EX_REGISTERDROP 0x00000002 /* TCM_SETEXTENDEDSTYLE */
+
+
+#define TCM_FIRST 0x1300
+
+#define TCM_GETIMAGELIST (TCM_FIRST + 2)
+#define TCM_SETIMAGELIST (TCM_FIRST + 3)
+#define TCM_GETITEMCOUNT (TCM_FIRST + 4)
+#define TCM_GETITEM WINELIB_NAME_AW(TCM_GETITEM)
+#define TCM_GETITEMA (TCM_FIRST + 5)
+#define TCM_GETITEMW (TCM_FIRST + 60)
+#define TCM_SETITEMA (TCM_FIRST + 6)
+#define TCM_SETITEMW (TCM_FIRST + 61)
+#define TCM_SETITEM WINELIB_NAME_AW(TCM_SETITEM)
+#define TCM_INSERTITEMA (TCM_FIRST + 7)
+#define TCM_INSERTITEMW (TCM_FIRST + 62)
+#define TCM_INSERTITEM WINELIB_NAME_AW(TCM_INSERTITEM)
+#define TCM_DELETEITEM (TCM_FIRST + 8)
+#define TCM_DELETEALLITEMS (TCM_FIRST + 9)
+#define TCM_GETITEMRECT (TCM_FIRST + 10)
+#define TCM_GETCURSEL (TCM_FIRST + 11)
+#define TCM_SETCURSEL (TCM_FIRST + 12)
+#define TCM_HITTEST (TCM_FIRST + 13)
+#define TCM_SETITEMEXTRA (TCM_FIRST + 14)
+#define TCM_ADJUSTRECT (TCM_FIRST + 40)
+#define TCM_SETITEMSIZE (TCM_FIRST + 41)
+#define TCM_REMOVEIMAGE (TCM_FIRST + 42)
+#define TCM_SETPADDING (TCM_FIRST + 43)
+#define TCM_GETROWCOUNT (TCM_FIRST + 44)
+#define TCM_GETTOOLTIPS (TCM_FIRST + 45)
+#define TCM_SETTOOLTIPS (TCM_FIRST + 46)
+#define TCM_GETCURFOCUS (TCM_FIRST + 47)
+#define TCM_SETCURFOCUS (TCM_FIRST + 48)
+#define TCM_SETMINTABWIDTH (TCM_FIRST + 49)
+#define TCM_DESELECTALL (TCM_FIRST + 50)
+#define TCM_HIGHLIGHTITEM (TCM_FIRST + 51)
+#define TCM_SETEXTENDEDSTYLE (TCM_FIRST + 52)
+#define TCM_GETEXTENDEDSTYLE (TCM_FIRST + 53)
+#define TCM_SETUNICODEFORMAT CCM_SETUNICODEFORMAT
+#define TCM_GETUNICODEFORMAT CCM_GETUNICODEFORMAT
+
+
+#define TCIF_TEXT 0x0001
+#define TCIF_IMAGE 0x0002
+#define TCIF_RTLREADING 0x0004
+#define TCIF_PARAM 0x0008
+#define TCIF_STATE 0x0010
+
+#define TCIS_BUTTONPRESSED 0x0001
+#define TCIS_HIGHLIGHTED 0x0002
+
+/* TabCtrl Macros */
+#define TabCtrl_GetImageList(hwnd) \
+ (HIMAGELIST)SNDMSGA((hwnd), TCM_GETIMAGELIST, 0, 0L)
+#define TabCtrl_SetImageList(hwnd, himl) \
+ (HIMAGELIST)SNDMSGA((hwnd), TCM_SETIMAGELIST, 0, (LPARAM)(UINT)(HIMAGELIST)(himl))
+#define TabCtrl_GetItemCount(hwnd) \
+ (int)SNDMSGA((hwnd), TCM_GETITEMCOUNT, 0, 0L)
+#define TabCtrl_GetItemA(hwnd, iItem, pitem) \
+ (BOOL)SNDMSGA((hwnd), TCM_GETITEM, (WPARAM)(int)iItem, (LPARAM)(TC_ITEM *)(pitem))
+#define TabCtrl_GetItemW(hwnd, iItem, pitem) \
+ (BOOL)SNDMSGW((hwnd), TCM_GETITEM, (WPARAM)(int)iItem, (LPARAM)(TC_ITEM *)(pitem))
+#define TabCtrl_GetItem WINELIB_NAME_AW(TabCtrl_GetItem)
+#define TabCtrl_SetItemA(hwnd, iItem, pitem) \
+ (BOOL)SNDMSGA((hwnd), TCM_SETITEM, (WPARAM)(int)iItem, (LPARAM)(TC_ITEM *)(pitem))
+#define TabCtrl_SetItemW(hwnd, iItem, pitem) \
+ (BOOL)SNDMSGW((hwnd), TCM_SETITEM, (WPARAM)(int)iItem, (LPARAM)(TC_ITEM *)(pitem))
+#define TabCtrl_SetItem WINELIB_NAME_AW(TabCtrl_GetItem)
+#define TabCtrl_InsertItemA(hwnd, iItem, pitem) \
+ (int)SNDMSGA((hwnd), TCM_INSERTITEM, (WPARAM)(int)iItem, (LPARAM)(const TC_ITEM *)(pitem))
+#define TabCtrl_InsertItemW(hwnd, iItem, pitem) \
+ (int)SNDMSGW((hwnd), TCM_INSERTITEM, (WPARAM)(int)iItem, (LPARAM)(const TC_ITEM *)(pitem))
+#define TabCtrl_InsertItem WINELIB_NAME_AW(TabCtrl_InsertItem)
+#define TabCtrl_DeleteItem(hwnd, i) \
+ (BOOL)SNDMSGA((hwnd), TCM_DELETEITEM, (WPARAM)(int)(i), 0L)
+#define TabCtrl_DeleteAllItems(hwnd) \
+ (BOOL)SNDMSGA((hwnd), TCM_DELETEALLITEMS, 0, 0L)
+#define TabCtrl_GetItemRect(hwnd, i, prc) \
+ (BOOL)SNDMSGA((hwnd), TCM_GETITEMRECT, (WPARAM)(int)(i), (LPARAM)(RECT *)(prc))
+#define TabCtrl_GetCurSel(hwnd) \
+ (int)SNDMSGA((hwnd), TCM_GETCURSEL, 0, 0)
+#define TabCtrl_SetCurSel(hwnd, i) \
+ (int)SNDMSGA((hwnd), TCM_SETCURSEL, (WPARAM)i, 0)
+#define TabCtrl_HitTest(hwndTC, pinfo) \
+ (int)SNDMSGA((hwndTC), TCM_HITTEST, 0, (LPARAM)(TC_HITTESTINFO *)(pinfo))
+#define TabCtrl_SetItemExtra(hwndTC, cb) \
+ (BOOL)SNDMSGA((hwndTC), TCM_SETITEMEXTRA, (WPARAM)(cb), 0L)
+#define TabCtrl_AdjustRect(hwnd, bLarger, prc) \
+ (int)SNDMSGA(hwnd, TCM_ADJUSTRECT, (WPARAM)(BOOL)bLarger, (LPARAM)(RECT *)prc)
+#define TabCtrl_SetItemSize(hwnd, x, y) \
+ (DWORD)SNDMSGA((hwnd), TCM_SETITEMSIZE, 0, MAKELPARAM(x,y))
+#define TabCtrl_RemoveImage(hwnd, i) \
+ (void)SNDMSGA((hwnd), TCM_REMOVEIMAGE, i, 0L)
+#define TabCtrl_SetPadding(hwnd, cx, cy) \
+ (void)SNDMSGA((hwnd), TCM_SETPADDING, 0, MAKELPARAM(cx, cy))
+#define TabCtrl_GetRowCount(hwnd) \
+ (int)SNDMSGA((hwnd), TCM_GETROWCOUNT, 0, 0L)
+#define TabCtrl_GetToolTips(hwnd) \
+ (HWND)SNDMSGA((hwnd), TCM_GETTOOLTIPS, 0, 0L)
+#define TabCtrl_SetToolTips(hwnd, hwndTT) \
+ (void)SNDMSGA((hwnd), TCM_SETTOOLTIPS, (WPARAM)hwndTT, 0L)
+#define TabCtrl_GetCurFocus(hwnd) \
+ (int)SNDMSGA((hwnd), TCM_GETCURFOCUS, 0, 0)
+#define TabCtrl_SetCurFocus(hwnd, i) \
+ SNDMSGA((hwnd),TCM_SETCURFOCUS, i, 0)
+#define TabCtrl_SetMinTabWidth(hwnd, x) \
+ (int)SNDMSGA((hwnd), TCM_SETMINTABWIDTH, 0, x)
+#define TabCtrl_DeselectAll(hwnd, fExcludeFocus)\
+ (void)SNDMSGA((hwnd), TCM_DESELECTALL, fExcludeFocus, 0)
+
+
+/* constants for TCHITTESTINFO */
+
+#define TCHT_NOWHERE 0x01
+#define TCHT_ONITEMICON 0x02
+#define TCHT_ONITEMLABEL 0x04
+#define TCHT_ONITEM (TCHT_ONITEMICON | TCHT_ONITEMLABEL)
+
+
+typedef struct tagTCITEMA {
+ UINT mask;
+ UINT dwState;
+ UINT dwStateMask;
+ LPSTR pszText;
+ INT cchTextMax;
+ INT iImage;
+ LPARAM lParam;
+} TCITEMA, *LPTCITEMA;
+
+typedef struct tagTCITEMW
+{
+ UINT mask;
+ DWORD dwState;
+ DWORD dwStateMask;
+ LPWSTR pszText;
+ INT cchTextMax;
+ INT iImage;
+ LPARAM lParam;
+} TCITEMW, *LPTCITEMW;
+
+#define TCITEM WINELIB_NAME_AW(TCITEM)
+#define LPTCITEM WINELIB_NAME_AW(LPTCITEM)
+#define TC_ITEM TCITEM
+
+#define TCN_FIRST (0U-550U)
+#define TCN_LAST (0U-580U)
+#define TCN_KEYDOWN (TCN_FIRST - 0)
+#define TCN_SELCHANGE (TCN_FIRST - 1)
+#define TCN_SELCHANGING (TCN_FIRST - 2)
+#define TCN_GETOBJECT (TCN_FIRST - 3)
+
+#include "pshpack1.h"
+typedef struct tagTCKEYDOWN
+{
+ NMHDR hdr;
+ WORD wVKey;
+ UINT flags;
+} NMTCKEYDOWN;
+#include "poppack.h"
+
+#define TC_KEYDOWN NMTCKEYDOWN
+
+/* ComboBoxEx control */
+
+#define WC_COMBOBOXEXA "ComboBoxEx32"
+#if defined(__GNUC__)
+# define WC_COMBOBOXEXW (const WCHAR []){ 'C','o','m','b','o', \
+ 'B','o','x','E','x','3','2',0 }
+#elif defined(_MSC_VER)
+# define WC_COMBOBOXEXW L"ComboBoxEx32"
+#else
+static const WCHAR WC_COMBOBOXEXW[] = { 'C','o','m','b','o',
+ 'B','o','x','E','x','3','2',0 };
+#endif
+#define WC_COMBOBOXEX WINELIB_NAME_AW(WC_COMBOBOXEX)
+
+#define CBEIF_TEXT 0x00000001
+#define CBEIF_IMAGE 0x00000002
+#define CBEIF_SELECTEDIMAGE 0x00000004
+#define CBEIF_OVERLAY 0x00000008
+#define CBEIF_INDENT 0x00000010
+#define CBEIF_LPARAM 0x00000020
+#define CBEIF_DI_SETITEM 0x10000000
+
+#define CBEM_INSERTITEMA (WM_USER+1)
+#define CBEM_INSERTITEMW (WM_USER+11)
+#define CBEM_INSERTITEM WINELIB_NAME_AW(CBEM_INSERTITEM)
+#define CBEM_SETIMAGELIST (WM_USER+2)
+#define CBEM_GETIMAGELIST (WM_USER+3)
+#define CBEM_GETITEMA (WM_USER+4)
+#define CBEM_GETITEMW (WM_USER+13)
+#define CBEM_GETITEM WINELIB_NAME_AW(CBEM_GETITEM)
+#define CBEM_SETITEMA (WM_USER+5)
+#define CBEM_SETITEMW (WM_USER+12)
+#define CBEM_SETITEM WINELIB_NAME_AW(CBEM_SETITEM)
+#define CBEM_DELETEITEM CB_DELETESTRING
+#define CBEM_GETCOMBOCONTROL (WM_USER+6)
+#define CBEM_GETEDITCONTROL (WM_USER+7)
+#define CBEM_SETEXSTYLE (WM_USER+8)
+#define CBEM_GETEXSTYLE (WM_USER+9)
+#define CBEM_GETEXTENDEDSTYLE (WM_USER+9)
+#define CBEM_SETEXTENDEDSTYLE (WM_USER+14)
+#define CBEM_SETUNICODEFORMAT CCM_SETUNICODEFORMAT
+#define CBEM_GETUNICODEFORMAT CCM_GETUNICODEFORMAT
+#define CBEM_HASEDITCHANGED (WM_USER+10)
+
+#define CBEIF_TEXT 0x00000001
+#define CBEIF_IMAGE 0x00000002
+#define CBEIF_SELECTEDIMAGE 0x00000004
+#define CBEIF_OVERLAY 0x00000008
+#define CBEIF_INDENT 0x00000010
+#define CBEIF_LPARAM 0x00000020
+#define CBEIF_DI_SETITEM 0x10000000
+
+#define CBEN_FIRST (0U-800U)
+#define CBEN_LAST (0U-830U)
+
+#define CBEN_GETDISPINFOA (CBEN_FIRST - 0)
+#define CBEN_GETDISPINFOW (CBEN_FIRST - 7)
+#define CBEN_GETDISPINFO WINELIB_NAME_AW(CBEN_GETDISPINFO)
+#define CBEN_INSERTITEM (CBEN_FIRST - 1)
+#define CBEN_DELETEITEM (CBEN_FIRST - 2)
+#define CBEN_BEGINEDIT (CBEN_FIRST - 4)
+#define CBEN_ENDEDITA (CBEN_FIRST - 5)
+#define CBEN_ENDEDITW (CBEN_FIRST - 6)
+#define CBEN_ENDEDIT WINELIB_NAME_AW(CBEN_ENDEDIT)
+#define CBEN_DRAGBEGINA (CBEN_FIRST - 8)
+#define CBEN_DRAGBEGINW (CBEN_FIRST - 9)
+#define CBEN_DRAGBEGIN WINELIB_NAME_AW(CBEN_DRAGBEGIN)
+
+#define CBES_EX_NOEDITIMAGE 0x00000001
+#define CBES_EX_NOEDITIMAGEINDENT 0x00000002
+#define CBES_EX_PATHWORDBREAKPROC 0x00000004
+#define CBES_EX_NOSIZELIMIT 0x00000008
+#define CBES_EX_CASESENSITIVE 0x00000010
+
+
+typedef struct tagCOMBOBOXEXITEMA
+{
+ UINT mask;
+ int iItem;
+ LPSTR pszText;
+ int cchTextMax;
+ int iImage;
+ int iSelectedImage;
+ int iOverlay;
+ int iIndent;
+ LPARAM lParam;
+} COMBOBOXEXITEMA, *PCOMBOBOXEXITEMA;
+typedef COMBOBOXEXITEMA const *PCCOMBOEXITEMA; /* Yes, there's a BOX missing */
+
+typedef struct tagCOMBOBOXEXITEMW
+{
+ UINT mask;
+ int iItem;
+ LPWSTR pszText;
+ int cchTextMax;
+ int iImage;
+ int iSelectedImage;
+ int iOverlay;
+ int iIndent;
+ LPARAM lParam;
+} COMBOBOXEXITEMW, *PCOMBOBOXEXITEMW;
+typedef COMBOBOXEXITEMW const *PCCOMBOEXITEMW; /* Yes, there's a BOX missing */
+
+#define COMBOBOXEXITEM WINELIB_NAME_AW(COMBOBOXEXITEM)
+#define PCOMBOBOXEXITEM WINELIB_NAME_AW(PCOMBOBOXEXITEM)
+#define PCCOMBOBOXEXITEM WINELIB_NAME_AW(PCCOMBOEXITEM) /* Yes, there's a BOX missing */
+
+#define CBENF_KILLFOCUS 1
+#define CBENF_RETURN 2
+#define CBENF_ESCAPE 3
+#define CBENF_DROPDOWN 4
+
+#define CBEMAXSTRLEN 260
+
+typedef struct tagNMCBEENDEDITW
+{
+ NMHDR hdr;
+ BOOL fChanged;
+ int iNewSelection;
+ WCHAR szText[CBEMAXSTRLEN];
+ int iWhy;
+} NMCBEENDEDITW, *LPNMCBEENDEDITW, *PNMCBEENDEDITW;
+
+typedef struct tagNMCBEENDEDITA
+{
+ NMHDR hdr;
+ BOOL fChanged;
+ int iNewSelection;
+ char szText[CBEMAXSTRLEN];
+ int iWhy;
+} NMCBEENDEDITA, *LPNMCBEENDEDITA, *PNMCBEENDEDITA;
+
+#define NMCBEENDEDIT WINELIB_NAME_AW(NMCBEENDEDIT)
+#define LPNMCBEENDEDIT WINELIB_NAME_AW(LPNMCBEENDEDIT)
+#define PNMCBEENDEDIT WINELIB_NAME_AW(PNMCBEENDEDIT)
+
+typedef struct
+{
+ NMHDR hdr;
+ COMBOBOXEXITEMA ceItem;
+} NMCOMBOBOXEXA, *PNMCOMBOBOXEXA;
+
+typedef struct
+{
+ NMHDR hdr;
+ COMBOBOXEXITEMW ceItem;
+} NMCOMBOBOXEXW, *PNMCOMBOBOXEXW;
+
+#define NMCOMBOBOXEX WINELIB_NAME_AW(NMCOMBOBOXEX)
+#define PNMCOMBOBOXEX WINELIB_NAME_AW(PNMCOMBOBOXEX)
+
+typedef struct
+{
+ NMHDR hdr;
+ int iItemid;
+ char szText[CBEMAXSTRLEN];
+} NMCBEDRAGBEGINA, *PNMCBEDRAGBEGINA, *LPNMCBEDRAGBEGINA;
+
+typedef struct
+{
+ NMHDR hdr;
+ int iItemid;
+ WCHAR szText[CBEMAXSTRLEN];
+} NMCBEDRAGBEGINW, *PNMCBEDRAGBEGINW, *LPNMCBEDRAGBEGINW;
+
+#define NMCBEDRAGBEGIN WINELIB_NAME_AW(NMCBEDRAGBEGIN)
+#define PNMCBEDRAGBEGIN WINELIB_NAME_AW(PNMCBEDRAGBEGIN)
+#define LPNMCBEDRAGBEGIN WINELIB_NAME_AW(LPNMCBEDRAGBEGIN)
+
+
+/* Hotkey control */
+
+#define HOTKEY_CLASS16 "msctls_hotkey"
+#define HOTKEY_CLASSA "msctls_hotkey32"
+#if defined(__GNUC__)
+# define HOTKEY_CLASSW (const WCHAR []){ 'm','s','c','t','l','s','_', \
+ 'h','o','t','k','e','y','3','2',0 }
+#elif defined(_MSC_VER)
+# define HOTKEY_CLASSW L"msctls_hotkey32"
+#else
+static const WCHAR HOTKEY_CLASSW[] = { 'm','s','c','t','l','s','_',
+ 'h','o','t','k','e','y','3','2',0 };
+#endif
+#define HOTKEY_CLASS WINELIB_NAME_AW(HOTKEY_CLASS)
+
+#define HOTKEYF_SHIFT 0x01
+#define HOTKEYF_CONTROL 0x02
+#define HOTKEYF_ALT 0x04
+#define HOTKEYF_EXT 0x08
+
+#define HKCOMB_NONE 0x0001
+#define HKCOMB_S 0x0002
+#define HKCOMB_C 0x0004
+#define HKCOMB_A 0x0008
+#define HKCOMB_SC 0x0010
+#define HKCOMB_SA 0x0020
+#define HKCOMB_CA 0x0040
+#define HKCOMB_SCA 0x0080
+
+#define HKM_SETHOTKEY (WM_USER+1)
+#define HKM_GETHOTKEY (WM_USER+2)
+#define HKM_SETRULES (WM_USER+3)
+
+
+/* animate control */
+
+#define ANIMATE_CLASSA "SysAnimate32"
+#if defined(__GNUC__)
+# define ANIMATE_CLASSW (const WCHAR []){ 'S','y','s', \
+ 'A','n','i','m','a','t','e','3','2',0 }
+#elif defined(_MSC_VER)
+# define ANIMATE_CLASSW L"SysAnimate32"
+#else
+static const WCHAR ANIMATE_CLASSW[] = { 'S','y','s',
+ 'A','n','i','m','a','t','e','3','2',0 };
+#endif
+#define ANIMATE_CLASS WINELIB_NAME_AW(ANIMATE_CLASS)
+
+#define ACS_CENTER 0x0001
+#define ACS_TRANSPARENT 0x0002
+#define ACS_AUTOPLAY 0x0004
+#define ACS_TIMER 0x0008 /* no threads, just timers */
+
+#define ACM_OPENA (WM_USER+100)
+#define ACM_OPENW (WM_USER+103)
+#define ACM_OPEN WINELIB_NAME_AW(ACM_OPEN)
+#define ACM_PLAY (WM_USER+101)
+#define ACM_STOP (WM_USER+102)
+
+#define ACN_START 1
+#define ACN_STOP 2
+
+#define Animate_CreateA(hwndP,id,dwStyle,hInstance) \
+ CreateWindowA(ANIMATE_CLASSA,NULL,dwStyle,0,0,0,0,hwndP,(HMENU)(id),hInstance,NULL)
+#define Animate_CreateW(hwndP,id,dwStyle,hInstance) \
+ CreateWindowW(ANIMATE_CLASSW,NULL,dwStyle,0,0,0,0,hwndP,(HMENU)(id),hInstance,NULL)
+#define Animate_Create WINELIB_NAME_AW(Animate_Create)
+#define Animate_OpenA(hwnd,szName) \
+ (BOOL)SNDMSGA(hwnd,ACM_OPENA,0,(LPARAM)(LPSTR)(szName))
+#define Animate_OpenW(hwnd,szName) \
+ (BOOL)SNDMSGW(hwnd,ACM_OPENW,0,(LPARAM)(LPWSTR)(szName))
+#define Animate_Open WINELIB_NAME_AW(Animate_Open)
+#define Animate_OpenExA(hwnd,hInst,szName) \
+ (BOOL)SNDMSGA(hwnd,ACM_OPENA,(WPARAM)hInst,(LPARAM)(LPSTR)(szName))
+#define Animate_OpenExW(hwnd,hInst,szName) \
+ (BOOL)SNDMSGW(hwnd,ACM_OPENW,(WPARAM)hInst,(LPARAM)(LPWSTR)(szName))
+#define Animate_OpenEx WINELIB_NAME_AW(Animate_OpenEx)
+#define Animate_Play(hwnd,from,to,rep) \
+ (BOOL)SNDMSGA(hwnd,ACM_PLAY,(WPARAM)(UINT)(rep),(LPARAM)MAKELONG(from,to))
+#define Animate_Stop(hwnd) \
+ (BOOL)SNDMSGA(hwnd,ACM_STOP,0,0)
+#define Animate_Close(hwnd) \
+ (BOOL)SNDMSGA(hwnd,ACM_OPENA,0,0)
+#define Animate_Seek(hwnd,frame) \
+ (BOOL)SNDMSGA(hwnd,ACM_PLAY,1,(LPARAM)MAKELONG(frame,frame))
+
+
+/**************************************************************************
+ * IP Address control
+ */
+
+#define WC_IPADDRESSA "SysIPAddress32"
+#if defined(__GNUC__)
+# define WC_IPADDRESSW (const WCHAR []){ 'S','y','s', \
+ 'I','P','A','d','d','r','e','s','s','3','2',0 }
+#elif defined(_MSC_VER)
+# define WC_IPADDRESSW L"SysIPAddress32"
+#else
+static const WCHAR WC_IPADDRESSW[] = { 'S','y','s',
+ 'I','P','A','d','d','r','e','s','s','3','2',0 };
+#endif
+#define WC_IPADDRESS WINELIB_NAME_AW(WC_IPADDRESS)
+
+#define IPM_CLEARADDRESS (WM_USER+100)
+#define IPM_SETADDRESS (WM_USER+101)
+#define IPM_GETADDRESS (WM_USER+102)
+#define IPM_SETRANGE (WM_USER+103)
+#define IPM_SETFOCUS (WM_USER+104)
+#define IPM_ISBLANK (WM_USER+105)
+
+#define IPN_FIRST (0U-860U)
+#define IPN_LAST (0U-879U)
+#define IPN_FIELDCHANGED (IPN_FIRST-0)
+
+typedef struct tagNMIPADDRESS
+{
+ NMHDR hdr;
+ INT iField;
+ INT iValue;
+} NMIPADDRESS, *LPNMIPADDRESS;
+
+#define MAKEIPRANGE(low,high) \
+ ((LPARAM)(WORD)(((BYTE)(high)<<8)+(BYTE)(low)))
+#define MAKEIPADDRESS(b1,b2,b3,b4) \
+ ((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<16)+((DWORD)(b3)<<8)+((DWORD)(b4))))
+
+#define FIRST_IPADDRESS(x) (((x)>>24)&0xff)
+#define SECOND_IPADDRESS(x) (((x)>>16)&0xff)
+#define THIRD_IPADDRESS(x) (((x)>>8)&0xff)
+#define FOURTH_IPADDRESS(x) ((x)&0xff)
+
+
+/**************************************************************************
+ * Native Font control
+ */
+
+#define WC_NATIVEFONTCTLA "NativeFontCtl"
+#if defined(__GNUC__)
+# define WC_NATIVEFONTCTLW (const WCHAR []){ 'N','a','t','i','v','e', \
+ 'F','o','n','t','C','t','l',0 }
+#elif defined(_MSC_VER)
+# define WC_NATIVEFONTCTLW L"NativeFontCtl"
+#else
+static const WCHAR WC_NATIVEFONTCTLW[] = { 'N','a','t','i','v','e',
+ 'F','o','n','t','C','t','l',0 };
+#endif
+#define WC_NATIVEFONTCTL WINELIB_NAME_AW(WC_NATIVEFONTCTL)
+
+#define NFS_EDIT 0x0001
+#define NFS_STATIC 0x0002
+#define NFS_LISTCOMBO 0x0004
+#define NFS_BUTTON 0x0008
+#define NFS_ALL 0x0010
+
+
+/**************************************************************************
+ * Month calendar control
+ *
+ */
+
+#define MONTHCAL_CLASSA "SysMonthCal32"
+#if defined(__GNUC__)
+# define MONTHCAL_CLASSW (const WCHAR []){ 'S','y','s', \
+ 'M','o','n','t','h','C','a','l','3','2',0 }
+#elif defined(_MSC_VER)
+# define MONTHCAL_CLASSW L"SysMonthCal32"
+#else
+static const WCHAR MONTHCAL_CLASSW[] = { 'S','y','s',
+ 'M','o','n','t','h','C','a','l','3','2',0 };
+#endif
+#define MONTHCAL_CLASS WINELIB_NAME_AW(MONTHCAL_CLASS)
+
+#define MCM_FIRST 0x1000
+#define MCN_FIRST (0U-750U)
+#define MCN_LAST (0U-759U)
+
+
+#define MCM_GETCURSEL (MCM_FIRST + 1)
+#define MCM_SETCURSEL (MCM_FIRST + 2)
+#define MCM_GETMAXSELCOUNT (MCM_FIRST + 3)
+#define MCM_SETMAXSELCOUNT (MCM_FIRST + 4)
+#define MCM_GETSELRANGE (MCM_FIRST + 5)
+#define MCM_SETSELRANGE (MCM_FIRST + 6)
+#define MCM_GETMONTHRANGE (MCM_FIRST + 7)
+#define MCM_SETDAYSTATE (MCM_FIRST + 8)
+#define MCM_GETMINREQRECT (MCM_FIRST + 9)
+#define MCM_SETCOLOR (MCM_FIRST + 10)
+#define MCM_GETCOLOR (MCM_FIRST + 11)
+#define MCM_SETTODAY (MCM_FIRST + 12)
+#define MCM_GETTODAY (MCM_FIRST + 13)
+#define MCM_HITTEST (MCM_FIRST + 14)
+#define MCM_SETFIRSTDAYOFWEEK (MCM_FIRST + 15)
+#define MCM_GETFIRSTDAYOFWEEK (MCM_FIRST + 16)
+#define MCM_GETRANGE (MCM_FIRST + 17)
+#define MCM_SETRANGE (MCM_FIRST + 18)
+#define MCM_GETMONTHDELTA (MCM_FIRST + 19)
+#define MCM_SETMONTHDELTA (MCM_FIRST + 20)
+#define MCM_GETMAXTODAYWIDTH (MCM_FIRST + 21)
+#define MCM_GETUNICODEFORMAT CCM_GETUNICODEFORMAT
+#define MCM_SETUNICODEFORMAT CCM_SETUNICODEFORMAT
+
+
+/* Notifications */
+
+#define MCN_SELCHANGE (MCN_FIRST + 1)
+#define MCN_GETDAYSTATE (MCN_FIRST + 3)
+#define MCN_SELECT (MCN_FIRST + 4)
+
+#define MCSC_BACKGROUND 0
+#define MCSC_TEXT 1
+#define MCSC_TITLEBK 2
+#define MCSC_TITLETEXT 3
+#define MCSC_MONTHBK 4
+#define MCSC_TRAILINGTEXT 5
+
+#define MCS_DAYSTATE 0x0001
+#define MCS_MULTISELECT 0x0002
+#define MCS_WEEKNUMBERS 0x0004
+#define MCS_NOTODAY 0x0010
+#define MCS_NOTODAYCIRCLE 0x0008
+
+#define MCHT_TITLE 0x00010000
+#define MCHT_CALENDAR 0x00020000
+#define MCHT_TODAYLINK 0x00030000
+
+#define MCHT_NEXT 0x01000000
+#define MCHT_PREV 0x02000000
+#define MCHT_NOWHERE 0x00000000
+#define MCHT_TITLEBK (MCHT_TITLE)
+#define MCHT_TITLEMONTH (MCHT_TITLE | 0x0001)
+#define MCHT_TITLEYEAR (MCHT_TITLE | 0x0002)
+#define MCHT_TITLEBTNNEXT (MCHT_TITLE | MCHT_NEXT | 0x0003)
+#define MCHT_TITLEBTNPREV (MCHT_TITLE | MCHT_PREV | 0x0003)
+
+#define MCHT_CALENDARBK (MCHT_CALENDAR)
+#define MCHT_CALENDARDATE (MCHT_CALENDAR | 0x0001)
+#define MCHT_CALENDARDATENEXT (MCHT_CALENDARDATE | MCHT_NEXT)
+#define MCHT_CALENDARDATEPREV (MCHT_CALENDARDATE | MCHT_PREV)
+#define MCHT_CALENDARDAY (MCHT_CALENDAR | 0x0002)
+#define MCHT_CALENDARWEEKNUM (MCHT_CALENDAR | 0x0003)
+
+
+
+#define GMR_VISIBLE 0
+#define GMR_DAYSTATE 1
+
+
+/* Month calendar's structures */
+
+
+typedef struct {
+ UINT cbSize;
+ POINT pt;
+ UINT uHit;
+ SYSTEMTIME st;
+} MCHITTESTINFO, *PMCHITTESTINFO;
+
+typedef struct tagNMSELCHANGE
+{
+ NMHDR nmhdr;
+ SYSTEMTIME stSelStart;
+ SYSTEMTIME stSelEnd;
+} NMSELCHANGE, *LPNMSELCHANGE;
+
+typedef NMSELCHANGE NMSELECT, *LPNMSELECT;
+typedef DWORD MONTHDAYSTATE, *LPMONTHDAYSTATE;
+
+typedef struct tagNMDAYSTATE
+{
+ NMHDR nmhdr;
+ SYSTEMTIME stStart;
+ int cDayState;
+ LPMONTHDAYSTATE prgDayState;
+} NMDAYSTATE, *LPNMDAYSTATE;
+
+
+/* macros */
+
+#define MonthCal_GetCurSel(hmc, pst) \
+ (BOOL)SNDMSGA(hmc, MCM_GETCURSEL, 0, (LPARAM)(pst))
+#define MonthCal_SetCurSel(hmc, pst) \
+ (BOOL)SNDMSGA(hmc, MCM_SETCURSEL, 0, (LPARAM)(pst))
+#define MonthCal_GetMaxSelCount(hmc) \
+ (DWORD)SNDMSGA(hmc, MCM_GETMAXSELCOUNT, 0, 0L)
+#define MonthCal_SetMaxSelCount(hmc, n) \
+ (BOOL)SNDMSGA(hmc, MCM_SETMAXSELCOUNT, (WPARAM)(n), 0L)
+#define MonthCal_GetSelRange(hmc, rgst) \
+ SNDMSGA(hmc, MCM_GETSELRANGE, 0, (LPARAM) (rgst))
+#define MonthCal_SetSelRange(hmc, rgst) \
+ SNDMSGA(hmc, MCM_SETSELRANGE, 0, (LPARAM) (rgst))
+#define MonthCal_GetMonthRange(hmc, gmr, rgst) \
+ (DWORD)SNDMSGA(hmc, MCM_GETMONTHRANGE, (WPARAM)(gmr), (LPARAM)(rgst))
+#define MonthCal_SetDayState(hmc, cbds, rgds) \
+ SNDMSGA(hmc, MCM_SETDAYSTATE, (WPARAM)(cbds), (LPARAM)(rgds))
+#define MonthCal_GetMinReqRect(hmc, prc) \
+ SNDMSGA(hmc, MCM_GETMINREQRECT, 0, (LPARAM)(prc))
+#define MonthCal_SetColor(hmc, iColor, clr)\
+ SNDMSGA(hmc, MCM_SETCOLOR, iColor, clr)
+#define MonthCal_GetColor(hmc, iColor) \
+ SNDMSGA(hmc, MCM_SETCOLOR, iColor, 0)
+#define MonthCal_GetToday(hmc, pst)\
+ (BOOL)SNDMSGA(hmc, MCM_GETTODAY, 0, (LPARAM)pst)
+#define MonthCal_SetToday(hmc, pst)\
+ SNDMSGA(hmc, MCM_SETTODAY, 0, (LPARAM)pst)
+#define MonthCal_HitTest(hmc, pinfo) \
+ SNDMSGA(hmc, MCM_HITTEST, 0, (LPARAM)(PMCHITTESTINFO)pinfo)
+#define MonthCal_SetFirstDayOfWeek(hmc, iDay) \
+ SNDMSGA(hmc, MCM_SETFIRSTDAYOFWEEK, 0, iDay)
+#define MonthCal_GetFirstDayOfWeek(hmc) \
+ (DWORD)SNDMSGA(hmc, MCM_GETFIRSTDAYOFWEEK, 0, 0)
+#define MonthCal_GetRange(hmc, rgst) \
+ (DWORD)SNDMSGA(hmc, MCM_GETRANGE, 0, (LPARAM)(rgst))
+#define MonthCal_SetRange(hmc, gd, rgst) \
+ (BOOL)SNDMSGA(hmc, MCM_SETRANGE, (WPARAM)(gd), (LPARAM)(rgst))
+#define MonthCal_GetMonthDelta(hmc) \
+ (int)SNDMSGA(hmc, MCM_GETMONTHDELTA, 0, 0)
+#define MonthCal_SetMonthDelta(hmc, n) \
+ (int)SNDMSGA(hmc, MCM_SETMONTHDELTA, n, 0)
+#define MonthCal_GetMaxTodayWidth(hmc) \
+ (DWORD)SNDMSGA(hmc, MCM_GETMAXTODAYWIDTH, 0, 0)
+#define MonthCal_SetUnicodeFormat(hwnd, fUnicode) \
+ (BOOL)SNDMSGA((hwnd), MCM_SETUNICODEFORMAT, (WPARAM)(fUnicode), 0)
+#define MonthCal_GetUnicodeFormat(hwnd) \
+ (BOOL)SNDMSGA((hwnd), MCM_GETUNICODEFORMAT, 0, 0)
+
+
+/**************************************************************************
+ * Date and time picker control
+ */
+
+#define DATETIMEPICK_CLASSA "SysDateTimePick32"
+#if defined(__GNUC__)
+# define DATETIMEPICK_CLASSW (const WCHAR []){ 'S','y','s', \
+ 'D','a','t','e','T','i','m','e','P','i','c','k','3','2',0 }
+#elif defined(_MSC_VER)
+# define DATETIMEPICK_CLASSW L"SysDateTimePick32"
+#else
+static const WCHAR DATETIMEPICK_CLASSW[] = { 'S','y','s',
+ 'D','a','t','e','T','i','m','e','P','i','c','k','3','2',0 };
+#endif
+#define DATETIMEPICK_CLASS WINELIB_NAME_AW(DATETIMEPICK_CLASS)
+
+#define DTM_FIRST 0x1000
+#define DTN_FIRST (0U-760U)
+#define DTN_LAST (0U-799U)
+
+
+#define DTM_GETSYSTEMTIME (DTM_FIRST+1)
+#define DTM_SETSYSTEMTIME (DTM_FIRST+2)
+#define DTM_GETRANGE (DTM_FIRST+3)
+#define DTM_SETRANGE (DTM_FIRST+4)
+#define DTM_SETFORMATA (DTM_FIRST+5)
+#define DTM_SETFORMATW (DTM_FIRST + 50)
+#define DTM_SETFORMAT WINELIB_NAME_AW(DTM_SETFORMAT)
+#define DTM_SETMCCOLOR (DTM_FIRST+6)
+#define DTM_GETMCCOLOR (DTM_FIRST+7)
+#define DTM_GETMONTHCAL (DTM_FIRST+8)
+#define DTM_SETMCFONT (DTM_FIRST+9)
+#define DTM_GETMCFONT (DTM_FIRST+10)
+
+
+/* Datetime Notifications */
+
+#define DTN_DATETIMECHANGE (DTN_FIRST + 1)
+#define DTN_USERSTRINGA (DTN_FIRST + 2)
+#define DTN_WMKEYDOWNA (DTN_FIRST + 3)
+#define DTN_FORMATA (DTN_FIRST + 4)
+#define DTN_FORMATQUERYA (DTN_FIRST + 5)
+#define DTN_DROPDOWN (DTN_FIRST + 6)
+#define DTN_CLOSEUP (DTN_FIRST + 7)
+#define DTN_USERSTRINGW (DTN_FIRST + 15)
+#define DTN_WMKEYDOWNW (DTN_FIRST + 16)
+#define DTN_FORMATW (DTN_FIRST + 17)
+#define DTN_FORMATQUERYW (DTN_FIRST + 18)
+
+#define DTN_USERSTRING WINELIB_NAME_AW(DTN_USERSTRING)
+#define DTN_WMKEYDOWN WINELIB_NAME_AW(DTN_WMKEYDOWN)
+#define DTN_FORMAT WINELIB_NAME_AW(DTN_FORMAT)
+#define DTN_FORMATQUERY WINELIB_NAME_AW(DTN_FORMATQUERY)
+
+#define DTS_SHORTDATEFORMAT 0x0000
+#define DTS_UPDOWN 0x0001
+#define DTS_SHOWNONE 0x0002
+#define DTS_LONGDATEFORMAT 0x0004
+#define DTS_TIMEFORMAT 0x0009
+#define DTS_APPCANPARSE 0x0010
+#define DTS_RIGHTALIGN 0x0020
+
+typedef struct tagNMDATETIMECHANGE
+{
+ NMHDR nmhdr;
+ DWORD dwFlags;
+ SYSTEMTIME st;
+} NMDATETIMECHANGE, *LPNMDATETIMECHANGE;
+
+typedef struct tagNMDATETIMESTRINGA
+{
+ NMHDR nmhdr;
+ LPCSTR pszUserString;
+ SYSTEMTIME st;
+ DWORD dwFlags;
+} NMDATETIMESTRINGA, *LPNMDATETIMESTRINGA;
+
+typedef struct tagNMDATETIMESTRINGW
+{
+ NMHDR nmhdr;
+ LPCWSTR pszUserString;
+ SYSTEMTIME st;
+ DWORD dwFlags;
+} NMDATETIMESTRINGW, *LPNMDATETIMESTRINGW;
+
+DECL_WINELIB_TYPE_AW(NMDATETIMESTRING)
+DECL_WINELIB_TYPE_AW(LPNMDATETIMESTRING)
+
+typedef struct tagNMDATETIMEWMKEYDOWNA
+{
+ NMHDR nmhdr;
+ int nVirtKey;
+ LPCSTR pszFormat;
+ SYSTEMTIME st;
+} NMDATETIMEWMKEYDOWNA, *LPNMDATETIMEWMKEYDOWNA;
+
+typedef struct tagNMDATETIMEWMKEYDOWNW
+{
+ NMHDR nmhdr;
+ int nVirtKey;
+ LPCWSTR pszFormat;
+ SYSTEMTIME st;
+} NMDATETIMEWMKEYDOWNW, *LPNMDATETIMEWMKEYDOWNW;
+
+DECL_WINELIB_TYPE_AW(NMDATETIMEWMKEYDOWN)
+DECL_WINELIB_TYPE_AW(LPNMDATETIMEWMKEYDOWN)
+
+typedef struct tagNMDATETIMEFORMATA
+{
+ NMHDR nmhdr;
+ LPCSTR pszFormat;
+ SYSTEMTIME st;
+ LPCSTR pszDisplay;
+ CHAR szDisplay[64];
+} NMDATETIMEFORMATA, *LPNMDATETIMEFORMATA;
+
+
+typedef struct tagNMDATETIMEFORMATW
+{
+ NMHDR nmhdr;
+ LPCWSTR pszFormat;
+ SYSTEMTIME st;
+ LPCWSTR pszDisplay;
+ WCHAR szDisplay[64];
+} NMDATETIMEFORMATW, *LPNMDATETIMEFORMATW;
+
+DECL_WINELIB_TYPE_AW(NMDATETIMEFORMAT)
+DECL_WINELIB_TYPE_AW(LPNMDATETIMEFORMAT)
+
+typedef struct tagNMDATETIMEFORMATQUERYA
+{
+ NMHDR nmhdr;
+ LPCSTR pszFormat;
+ SIZE szMax;
+} NMDATETIMEFORMATQUERYA, *LPNMDATETIMEFORMATQUERYA;
+
+typedef struct tagNMDATETIMEFORMATQUERYW
+{
+ NMHDR nmhdr;
+ LPCWSTR pszFormat;
+ SIZE szMax;
+} NMDATETIMEFORMATQUERYW, *LPNMDATETIMEFORMATQUERYW;
+
+DECL_WINELIB_TYPE_AW(NMDATETIMEFORMATQUERY)
+DECL_WINELIB_TYPE_AW(LPNMDATETIMEFORMATQUERY)
+
+
+
+#define GDT_ERROR -1
+#define GDT_VALID 0
+#define GDT_NONE 1
+
+#define GDTR_MIN 0x0001
+#define GDTR_MAX 0x0002
+
+
+#define DateTime_GetSystemtime(hdp, pst) \
+ (DWORD)SNDMSGA (hdp, DTM_GETSYSTEMTIME , 0, (LPARAM)(pst))
+#define DateTime_SetSystemtime(hdp, gd, pst) \
+ (BOOL)SNDMSGA (hdp, DTM_SETSYSTEMTIME, (LPARAM)(gd), (LPARAM)(pst))
+#define DateTime_GetRange(hdp, rgst) \
+ (DWORD)SNDMSGA (hdp, DTM_GETRANGE, 0, (LPARAM)(rgst))
+#define DateTime_SetRange(hdp, gd, rgst) \
+ (BOOL)SNDMSGA (hdp, DTM_SETRANGE, (WPARAM)(gd), (LPARAM)(rgst))
+#define DateTime_SetFormat WINELIB_NAME_AW(DateTime_SetFormat)
+#define DateTime_SetFormatA(hdp, sz) \
+ (BOOL)SNDMSGA (hdp, DTM_SETFORMAT, 0, (LPARAM)(sz))
+#define DateTime_SetFormatW(hdp, sz) \
+ (BOOL)SNDMSGW (hdp, DTM_SETFORMAT, 0, (LPARAM)(sz))
+#define DateTime_GetMonthCalColor(hdp, iColor) \
+ SNDMSGA (hdp, DTM_GETMCCOLOR, iColor, 0)
+#define DateTime_GetMonthCal(hdp) \
+ (HWND) SNDMSGA (hdp, DTM_GETMONTHCAL, 0, 0)
+#define DateTime_SetMonthCalFont(hdp, hfont, fRedraw) \
+ SNDMSGA (hdp, DTM_SETMCFONT, (WPARAM)hfont, (LPARAM)fRedraw)
+#define DateTime_GetMonthCalFont(hdp) \
+ SNDMSGA (hdp, DTM_GETMCFONT, 0, 0)
+
+
+
+
+
+
+/**************************************************************************
+ * UNDOCUMENTED functions
+ */
+
+/* private heap memory functions */
+
+LPVOID WINAPI COMCTL32_Alloc (DWORD);
+LPVOID WINAPI COMCTL32_ReAlloc (LPVOID, DWORD);
+BOOL WINAPI COMCTL32_Free (LPVOID);
+DWORD WINAPI COMCTL32_GetSize (LPVOID);
+
+LPWSTR WINAPI COMCTL32_StrChrW (LPCWSTR, WORD);
+
+
+INT WINAPI Str_GetPtrA (LPCSTR, LPSTR, INT);
+BOOL WINAPI Str_SetPtrA (LPSTR *, LPCSTR);
+INT WINAPI Str_GetPtrW (LPCWSTR, LPWSTR, INT);
+BOOL WINAPI Str_SetPtrW (LPWSTR *, LPCWSTR);
+#define Str_GetPtr WINELIB_NAME_AW(Str_GetPtr)
+#define Str_SetPtr WINELIB_NAME_AW(Str_SetPtr)
+
+
+/* Dynamic Storage Array */
+
+typedef struct _DSA
+{
+ INT nItemCount;
+ LPVOID pData;
+ INT nMaxCount;
+ INT nItemSize;
+ INT nGrow;
+} DSA, *HDSA;
+
+HDSA WINAPI DSA_Create (INT, INT);
+BOOL WINAPI DSA_DeleteAllItems (const HDSA);
+INT WINAPI DSA_DeleteItem (const HDSA, INT);
+BOOL WINAPI DSA_Destroy (const HDSA);
+BOOL WINAPI DSA_GetItem (const HDSA, INT, LPVOID);
+LPVOID WINAPI DSA_GetItemPtr (const HDSA, INT);
+INT WINAPI DSA_InsertItem (const HDSA, INT, LPVOID);
+BOOL WINAPI DSA_SetItem (const HDSA, INT, LPVOID);
+
+typedef INT (CALLBACK *DSAENUMPROC)(LPVOID, DWORD);
+VOID WINAPI DSA_EnumCallback (const HDSA, DSAENUMPROC, LPARAM);
+BOOL WINAPI DSA_DestroyCallback (const HDSA, DSAENUMPROC, LPARAM);
+
+
+/* Dynamic Pointer Array */
+
+typedef struct _DPA
+{
+ INT nItemCount;
+ LPVOID *ptrs;
+ HANDLE hHeap;
+ INT nGrow;
+ INT nMaxCount;
+} DPA, *HDPA;
+
+HDPA WINAPI DPA_Create (INT);
+HDPA WINAPI DPA_CreateEx (INT, HANDLE);
+BOOL WINAPI DPA_Destroy (const HDPA);
+HDPA WINAPI DPA_Clone (const HDPA, const HDPA);
+LPVOID WINAPI DPA_GetPtr (const HDPA, INT);
+INT WINAPI DPA_GetPtrIndex (const HDPA, LPVOID);
+BOOL WINAPI DPA_Grow (const HDPA, INT);
+BOOL WINAPI DPA_SetPtr (const HDPA, INT, LPVOID);
+INT WINAPI DPA_InsertPtr (const HDPA, INT, LPVOID);
+LPVOID WINAPI DPA_DeletePtr (const HDPA, INT);
+BOOL WINAPI DPA_DeleteAllPtrs (const HDPA);
+
+typedef INT (CALLBACK *PFNDPACOMPARE)(LPVOID, LPVOID, LPARAM);
+BOOL WINAPI DPA_Sort (const HDPA, PFNDPACOMPARE, LPARAM);
+
+#define DPAS_SORTED 0x0001
+#define DPAS_INSERTBEFORE 0x0002
+#define DPAS_INSERTAFTER 0x0004
+
+INT WINAPI DPA_Search (const HDPA, LPVOID, INT, PFNDPACOMPARE, LPARAM, UINT);
+
+#define DPAM_NOSORT 0x0001
+#define DPAM_INSERT 0x0004
+#define DPAM_DELETE 0x0008
+
+typedef PVOID (CALLBACK *PFNDPAMERGE)(DWORD,PVOID,PVOID,LPARAM);
+BOOL WINAPI DPA_Merge (const HDPA, const HDPA, DWORD, PFNDPACOMPARE, PFNDPAMERGE, LPARAM);
+
+typedef INT (CALLBACK *DPAENUMPROC)(LPVOID, DWORD);
+VOID WINAPI DPA_EnumCallback (const HDPA, DPAENUMPROC, LPARAM);
+BOOL WINAPI DPA_DestroyCallback (const HDPA, DPAENUMPROC, LPARAM);
+
+
+#define DPA_GetPtrCount(hdpa) (*(INT*)(hdpa))
+#define DPA_GetPtrPtr(hdpa) (*((LPVOID**)((BYTE*)(hdpa)+sizeof(INT))))
+#define DPA_FastGetPtr(hdpa,i) (DPA_GetPtrPtr(hdpa)[i])
+
+
+/* notification helper functions */
+
+LRESULT WINAPI COMCTL32_SendNotify (HWND, HWND, UINT, LPNMHDR);
+
+/* type and functionality of last parameter is still unknown */
+LRESULT WINAPI COMCTL32_SendNotifyEx (HWND, HWND, UINT, LPNMHDR, DWORD);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __WINE_COMMCTRL_H */
--- /dev/null
+/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+#include <msvcrt/ctype.h>
+
+unsigned short _ctype[] = {
+ 0, /* <EOF>, 0xFFFF */
+ _CONTROL, /* CTRL+@, 0x00 */
+ _CONTROL, /* CTRL+A, 0x01 */
+ _CONTROL, /* CTRL+B, 0x02 */
+ _CONTROL, /* CTRL+C, 0x03 */
+ _CONTROL, /* CTRL+D, 0x04 */
+ _CONTROL, /* CTRL+E, 0x05 */
+ _CONTROL, /* CTRL+F, 0x06 */
+ _CONTROL, /* CTRL+G, 0x07 */
+ _CONTROL, /* CTRL+H, 0x08 */
+ _CONTROL | _SPACE, /* CTRL+I, 0x09 */
+ _CONTROL | _SPACE, /* CTRL+J, 0x0a */
+ _CONTROL | _SPACE, /* CTRL+K, 0x0b */
+ _CONTROL | _SPACE, /* CTRL+L, 0x0c */
+ _CONTROL | _SPACE, /* CTRL+M, 0x0d */
+ _CONTROL, /* CTRL+N, 0x0e */
+ _CONTROL, /* CTRL+O, 0x0f */
+ _CONTROL, /* CTRL+P, 0x10 */
+ _CONTROL, /* CTRL+Q, 0x11 */
+ _CONTROL, /* CTRL+R, 0x12 */
+ _CONTROL, /* CTRL+S, 0x13 */
+ _CONTROL, /* CTRL+T, 0x14 */
+ _CONTROL, /* CTRL+U, 0x15 */
+ _CONTROL, /* CTRL+V, 0x16 */
+ _CONTROL, /* CTRL+W, 0x17 */
+ _CONTROL, /* CTRL+X, 0x18 */
+ _CONTROL, /* CTRL+Y, 0x19 */
+ _CONTROL, /* CTRL+Z, 0x1a */
+ _CONTROL, /* CTRL+[, 0x1b */
+ _CONTROL, /* CTRL+\, 0x1c */
+ _CONTROL, /* CTRL+], 0x1d */
+ _CONTROL, /* CTRL+^, 0x1e */
+ _CONTROL, /* CTRL+_, 0x1f */
+ _SPACE | _BLANK, /* ` ', 0x20 */
+ _PUNCT, /* `!', 0x21 */
+ _PUNCT, /* 0x22 */
+ _PUNCT, /* `#', 0x23 */
+ _PUNCT, /* `$', 0x24 */
+ _PUNCT, /* `%', 0x25 */
+ _PUNCT, /* `&', 0x26 */
+ _PUNCT, /* 0x27 */
+ _PUNCT, /* `(', 0x28 */
+ _PUNCT, /* `)', 0x29 */
+ _PUNCT, /* `*', 0x2a */
+ _PUNCT, /* `+', 0x2b */
+ _PUNCT, /* `,', 0x2c */
+ _PUNCT, /* `-', 0x2d */
+ _PUNCT, /* `.', 0x2e */
+ _PUNCT, /* `/', 0x2f */
+ _DIGIT | _HEX, /* `0', 0x30 */
+ _DIGIT | _HEX, /* `1', 0x31 */
+ _DIGIT | _HEX, /* `2', 0x32 */
+ _DIGIT | _HEX, /* `3', 0x33 */
+ _DIGIT | _HEX, /* `4', 0x34 */
+ _DIGIT | _HEX, /* `5', 0x35 */
+ _DIGIT | _HEX, /* `6', 0x36 */
+ _DIGIT | _HEX, /* `7', 0x37 */
+ _DIGIT | _HEX, /* `8', 0x38 */
+ _DIGIT | _HEX, /* `9', 0x39 */
+ _PUNCT, /* `:', 0x3a */
+ _PUNCT, /* `;', 0x3b */
+ _PUNCT, /* `<', 0x3c */
+ _PUNCT, /* `=', 0x3d */
+ _PUNCT, /* `>', 0x3e */
+ _PUNCT, /* `?', 0x3f */
+ _PUNCT, /* `@', 0x40 */
+ _UPPER | _HEX, /* `A', 0x41 */
+ _UPPER | _HEX, /* `B', 0x42 */
+ _UPPER | _HEX, /* `C', 0x43 */
+ _UPPER | _HEX, /* `D', 0x44 */
+ _UPPER | _HEX, /* `E', 0x45 */
+ _UPPER | _HEX, /* `F', 0x46 */
+ _UPPER, /* `G', 0x47 */
+ _UPPER, /* `H', 0x48 */
+ _UPPER, /* `I', 0x49 */
+ _UPPER, /* `J', 0x4a */
+ _UPPER, /* `K', 0x4b */
+ _UPPER, /* `L', 0x4c */
+ _UPPER, /* `M', 0x4d */
+ _UPPER, /* `N', 0x4e */
+ _UPPER, /* `O', 0x4f */
+ _UPPER, /* `P', 0x50 */
+ _UPPER, /* `Q', 0x51 */
+ _UPPER, /* `R', 0x52 */
+ _UPPER, /* `S', 0x53 */
+ _UPPER, /* `T', 0x54 */
+ _UPPER, /* `U', 0x55 */
+ _UPPER, /* `V', 0x56 */
+ _UPPER, /* `W', 0x57 */
+ _UPPER, /* `X', 0x58 */
+ _UPPER, /* `Y', 0x59 */
+ _UPPER, /* `Z', 0x5a */
+ _PUNCT, /* `[', 0x5b */
+ _PUNCT, /* 0x5c */
+ _PUNCT, /* `]', 0x5d */
+ _PUNCT, /* `^', 0x5e */
+ _PUNCT, /* `_', 0x5f */
+ _PUNCT, /* 0x60 */
+ _LOWER | _HEX, /* `a', 0x61 */
+ _LOWER | _HEX, /* `b', 0x62 */
+ _LOWER | _HEX, /* `c', 0x63 */
+ _LOWER | _HEX, /* `d', 0x64 */
+ _LOWER | _HEX, /* `e', 0x65 */
+ _LOWER | _HEX, /* `f', 0x66 */
+ _LOWER, /* `g', 0x67 */
+ _LOWER, /* `h', 0x68 */
+ _LOWER, /* `i', 0x69 */
+ _LOWER, /* `j', 0x6a */
+ _LOWER, /* `k', 0x6b */
+ _LOWER, /* `l', 0x6c */
+ _LOWER, /* `m', 0x6d */
+ _LOWER, /* `n', 0x6e */
+ _LOWER, /* `o', 0x6f */
+ _LOWER, /* `p', 0x70 */
+ _LOWER, /* `q', 0x71 */
+ _LOWER, /* `r', 0x72 */
+ _LOWER, /* `s', 0x73 */
+ _LOWER, /* `t', 0x74 */
+ _LOWER, /* `u', 0x75 */
+ _LOWER, /* `v', 0x76 */
+ _LOWER, /* `w', 0x77 */
+ _LOWER, /* `x', 0x78 */
+ _LOWER, /* `y', 0x79 */
+ _LOWER, /* `z', 0x7a */
+ _PUNCT, /* `{', 0x7b */
+ _PUNCT, /* `|', 0x7c */
+ _PUNCT, /* `}', 0x7d */
+ _PUNCT, /* `~', 0x7e */
+ _CONTROL, /* 0x7f */
+ 0, /* 0x80 */
+ 0, /* 0x81 */
+ 0, /* 0x82 */
+ 0, /* 0x83 */
+ 0, /* 0x84 */
+ 0, /* 0x85 */
+ 0, /* 0x86 */
+ 0, /* 0x87 */
+ 0, /* 0x88 */
+ 0, /* 0x89 */
+ 0, /* 0x8a */
+ 0, /* 0x8b */
+ 0, /* 0x8c */
+ 0, /* 0x8d */
+ 0, /* 0x8e */
+ 0, /* 0x8f */
+ 0, /* 0x90 */
+ 0, /* 0x91 */
+ 0, /* 0x92 */
+ 0, /* 0x93 */
+ 0, /* 0x94 */
+ 0, /* 0x95 */
+ 0, /* 0x96 */
+ 0, /* 0x97 */
+ 0, /* 0x98 */
+ 0, /* 0x99 */
+ 0, /* 0x9a */
+ 0, /* 0x9b */
+ 0, /* 0x9c */
+ 0, /* 0x9d */
+ 0, /* 0x9e */
+ 0, /* 0x9f */
+ 0, /* 0xa0 */
+ 0, /* 0xa1 */
+ 0, /* 0xa2 */
+ 0, /* 0xa3 */
+ 0, /* 0xa4 */
+ 0, /* 0xa5 */
+ 0, /* 0xa6 */
+ 0, /* 0xa7 */
+ 0, /* 0xa8 */
+ 0, /* 0xa9 */
+ 0, /* 0xaa */
+ 0, /* 0xab */
+ 0, /* 0xac */
+ 0, /* 0xad */
+ 0, /* 0xae */
+ 0, /* 0xaf */
+ 0, /* 0xb0 */
+ 0, /* 0xb1 */
+ 0, /* 0xb2 */
+ 0, /* 0xb3 */
+ 0, /* 0xb4 */
+ 0, /* 0xb5 */
+ 0, /* 0xb6 */
+ 0, /* 0xb7 */
+ 0, /* 0xb8 */
+ 0, /* 0xb9 */
+ 0, /* 0xba */
+ 0, /* 0xbb */
+ 0, /* 0xbc */
+ 0, /* 0xbd */
+ 0, /* 0xbe */
+ 0, /* 0xbf */
+ 0, /* 0xc0 */
+ 0, /* 0xc1 */
+ 0, /* 0xc2 */
+ 0, /* 0xc3 */
+ 0, /* 0xc4 */
+ 0, /* 0xc5 */
+ 0, /* 0xc6 */
+ 0, /* 0xc7 */
+ 0, /* 0xc8 */
+ 0, /* 0xc9 */
+ 0, /* 0xca */
+ 0, /* 0xcb */
+ 0, /* 0xcc */
+ 0, /* 0xcd */
+ 0, /* 0xce */
+ 0, /* 0xcf */
+ 0, /* 0xd0 */
+ 0, /* 0xd1 */
+ 0, /* 0xd2 */
+ 0, /* 0xd3 */
+ 0, /* 0xd4 */
+ 0, /* 0xd5 */
+ 0, /* 0xd6 */
+ 0, /* 0xd7 */
+ 0, /* 0xd8 */
+ 0, /* 0xd9 */
+ 0, /* 0xda */
+ 0, /* 0xdb */
+ 0, /* 0xdc */
+ 0, /* 0xdd */
+ 0, /* 0xde */
+ 0, /* 0xdf */
+ 0, /* 0xe0 */
+ 0, /* 0xe1 */
+ 0, /* 0xe2 */
+ 0, /* 0xe3 */
+ 0, /* 0xe4 */
+ 0, /* 0xe5 */
+ 0, /* 0xe6 */
+ 0, /* 0xe7 */
+ 0, /* 0xe8 */
+ 0, /* 0xe9 */
+ 0, /* 0xea */
+ 0, /* 0xeb */
+ 0, /* 0xec */
+ 0, /* 0xed */
+ 0, /* 0xee */
+ 0, /* 0xef */
+ 0, /* 0xf0 */
+ 0, /* 0xf1 */
+ 0, /* 0xf2 */
+ 0, /* 0xf3 */
+ 0, /* 0xf4 */
+ 0, /* 0xf5 */
+ 0, /* 0xf6 */
+ 0, /* 0xf7 */
+ 0, /* 0xf8 */
+ 0, /* 0xf9 */
+ 0, /* 0xfa */
+ 0, /* 0xfb */
+ 0, /* 0xfc */
+ 0, /* 0xfd */
+ 0, /* 0xfe */
+ 0 /* 0xff */
+};
+
+/* EOF */
--- /dev/null
+/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
+#include <msvcrt/assert.h>
+#include <msvcrt/stdio.h>
+#include <msvcrt/stdlib.h>
+#include <msvcrt/signal.h>
+
+
+void _assert(const char* msg, const char* file, int line)
+{
+ /* Assertion failed at foo.c line 45: x<y */
+ fprintf(stderr, "Assertion failed at %s line %d: %s\n", file, line, msg);
+ raise(SIGABRT);
+}
--- /dev/null
+#include <windows.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+
+void debug_printf(char* fmt, ...)
+{
+ va_list args;
+ char buffer[255];
+ HANDLE OutputHandle;
+
+ AllocConsole();
+ OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
+ va_start(args,fmt);
+ vsprintf(buffer,fmt,args);
+ WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL);
+ va_end(args);
+}
--- /dev/null
+/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
+#include <msvcrt/stdio.h>
+#include <msvcrt/internal/file.h>
+
+//wchar_t* fgetws(wchar_t* wcaBuffer, int nBufferSize, FILE* fileRead);
+//char* fgets(char *s, int n, FILE *f);
+//int _getw(FILE *stream);
+/*
+// Read a word (int) from STREAM.
+int _getw(FILE *stream)
+{
+ int w;
+
+ // Is there a better way?
+ if (fread( &w, sizeof(w), 1, stream) != 1)
+ return(EOF);
+ return(w);
+}
+
+//getc can be a macro
+#undef getc
+
+int getc(FILE *fp)
+{
+ int c = -1;
+// check for invalid stream
+ if ( !__validfp (fp) ) {
+ __set_errno(EINVAL);
+ return EOF;
+ }
+// check for read access on stream
+ if ( !OPEN4READING(fp) ) {
+ __set_errno(EINVAL);
+ return -1;
+ }
+ if(fp->_cnt > 0) {
+ fp->_cnt--;
+ c = (int)*fp->_ptr++;
+ }
+ else {
+ c = _filbuf(fp);
+ }
+ return c;
+}
+ */
+
+wchar_t* fgetws(wchar_t* s, int n, FILE* f)
+{
+ int c = 0;
+ wchar_t* cs;
+
+ cs = s;
+ while (--n > 0 && (c = _getw(f)) != EOF) {
+ *cs++ = c;
+ if (c == L'\n')
+ break;
+ }
+ if (c == EOF && cs == s) {
+ return NULL;
+ }
+ *cs++ = L'\0';
+ return s;
+}
--- /dev/null
+/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
+#include <windows.h>
+#include <msvcrt/stdio.h>
+#include <msvcrt/internal/file.h>
+#include <msvcrt/string.h>
+
+//int fputws(const wchar_t* wsOutput, FILE* fileWrite)
+//int fputs(const char *s, FILE *f)
+
+int
+fputws(const wchar_t* s, FILE* f)
+{
+ int r = 0;
+ int c;
+ int unbuffered;
+ wchar_t localbuf[BUFSIZ];
+
+ unbuffered = f->_flag & _IONBF;
+ if (unbuffered)
+ {
+ f->_flag &= ~_IONBF;
+ f->_ptr = f->_base = localbuf;
+ f->_bufsiz = BUFSIZ;
+ }
+
+ while ((c = *s++))
+ r = putwc(c, f);
+
+ if (unbuffered)
+ {
+ fflush(f);
+ f->_flag |= _IONBF;
+ f->_base = NULL;
+ f->_bufsiz = 0;
+ f->_cnt = 0;
+ }
+ return(r);
+}
--- /dev/null
+#include <windows.h>
+#include <msvcrt/stdlib.h>
+
+
+#undef alloca
+void *alloca(size_t s)
+{
+ register unsigned int as = s;
+
+// alloca(0) should not return the stack pointer
+ if ( s == 0 )
+ return NULL;
+
+
+ if ( (s & 0xfffffffc) != 0 )
+ as += 4;
+
+ as &= 0xfffffffc;
+
+ __asm__ __volatile__(
+ "mov %0, %%edx \n"
+// "popl %%ebp \n"
+ "leave \n"
+ "popl %%ecx \n"
+ "subl %%edx, %%esp \n"
+ "movl %%esp, %%eax \n"
+ "addl $20, %%eax \n"//4 bytes + 16 bytes = arguments
+ "push %%ecx \n"
+ "ret \n"
+ :
+ :"g" ( as)
+ );
+
+
+ return NULL;
+}
+
+void *_alloca(size_t s)
+{
+ register unsigned int as = s;
+
+// alloca(0) should not return the stack pointer
+ if ( s == 0 )
+ return NULL;
+
+
+ if ( (s & 0xfffffffc) != 0 )
+ as += 4;
+
+ as &= 0xfffffffc;
+
+ __asm__ __volatile__(
+ "mov %0, %%edx \n"
+// "popl %%ebp \n"
+ "leave \n"
+ "popl %%ecx \n"
+ "subl %%edx, %%esp \n"
+ "movl %%esp, %%eax \n"
+ "addl $20, %%eax \n"//4 bytes + 16 bytes = arguments
+ "push %%ecx \n"
+ "ret \n"
+ :
+ :"g" ( as)
+ );
+
+
+ return NULL;
+}
--- /dev/null
+#include <msvcrt/string.h>
+#include <msvcrt/ctype.h>
+#include <msvcrt/stdlib.h>
+
+
+int _daylight_dll;
+int _timezone_dll;
+
+
+void _set_daylight_export(int value)
+{
+ _daylight_dll = value;
+}
+
+void _set_timezone_export(int value)
+{
+ _timezone_dll = value;
+}
+
+
+
--- /dev/null
+/* This file is generated with wmc version 1.0.0 (12-Jun-2000). Do not edit! */
+/* Source : kernel32.mc */
+/* Cmdline: wmc -H ../../include/reactos/errcodes.h -o errcodes.rc kernel32.mc */
+/* Date : Tue Dec 10 02:07:21 2002 */
+
+LANGUAGE 0x9, 0x1
+1 MESSAGETABLE "MSG00409.bin"
--- /dev/null
+# $Id$
+
+PATH_TO_TOP = ../..
+
+#TARGET_TYPE = dynlink
+
+TARGETNAME = kernel32
+
+errcodes.rc: $(TARGETNAME).mc
+ $(MC) \
+ -H $(PATH_TO_TOP)/include/reactos/errcodes.h \
+ -o errcodes.rc \
+ $(TARGETNAME).mc
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
--- /dev/null
+#define NTOS_MODE_USER
+#include <ntos.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <limits.h>
+#include <wchar.h>
+#include <string.h>
+#include <assert.h>
+#include <ddk/ntddk.h>
+#include <ddk/ntddbeep.h>
+#include <ddk/ntddser.h>
+#include <windows.h>
+#include <kernel32/proc.h>
+#include <kernel32/thread.h>
+#include <kernel32/error.h>
+#include <ntdll/base.h>
+#include <ntdll/rtl.h>
+#include <ntdll/dbg.h>
+#include <ntdll/csr.h>
+#include <ntdll/ldr.h>
+#include <napi/i386/segment.h>
+#include <napi/teb.h>
+#include <napi/npipe.h>
+#include <ntos/minmax.h>
+#include <csrss/csrss.h>
+#include <reactos/buildno.h>
--- /dev/null
+;
+; kernel32.mc MESSAGE resources for kernel32.dll
+;
+
+MessageIdTypedef=ULONG
+
+SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS
+ Informational=0x1:STATUS_SEVERITY_INFORMATIONAL
+ Warning=0x2:STATUS_SEVERITY_WARNING
+ Error=0x3:STATUS_SEVERITY_ERROR
+ )
+
+FacilityNames=(System=0x0:FACILITY_SYSTEM
+ Runtime=0x2:FACILITY_RUNTIME
+ Stubs=0x3:FACILITY_STUBS
+ Io=0x4:FACILITY_IO_ERROR_CODE
+ )
+
+LanguageNames=(English=0x409:MSG00409)
+
+;
+; message definitions
+;
+
+MessageId=0x00
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SUCCESS
+Language=English
+ERROR_SUCCESS - The operation completed successfully.\r
+.
+
+MessageId=0x01
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_FUNCTION
+Language=English
+ERROR_INVALID_FUNCTION - Incorrect function.\r
+.
+
+MessageId=0x02
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FILE_NOT_FOUND
+Language=English
+ERROR_FILE_NOT_FOUND - The system cannot find the file specified.\r
+.
+
+MessageId=0x03
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PATH_NOT_FOUND
+Language=English
+ERROR_PATH_NOT_FOUND - The system cannot find the path specified.\r
+.
+
+MessageId=0x04
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_OPEN_FILES
+Language=English
+ERROR_TOO_MANY_OPEN_FILES - The system cannot open the file.\r
+.
+
+MessageId=0x05
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ACCESS_DENIED
+Language=English
+ERROR_ACCESS_DENIED - Access is denied.\r
+.
+
+MessageId=0x06
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_HANDLE
+Language=English
+ERROR_INVALID_HANDLE - The handle is invalid.\r
+.
+
+MessageId=0x07
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ARENA_TRASHED
+Language=English
+ERROR_ARENA_TRASHED - The storage control blocks were destroyed.\r
+.
+
+MessageId=0x08
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_ENOUGH_MEMORY
+Language=English
+ERROR_NOT_ENOUGH_MEMORY - Not enough storage is available to process this command.\r
+.
+
+MessageId=0x09
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_BLOCK
+Language=English
+ERROR_INVALID_BLOCK - The storage control block address is invalid.\r
+.
+
+MessageId=0x0A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_ENVIRONMENT
+Language=English
+ERROR_BAD_ENVIRONMENT - The environment is incorrect.\r
+.
+
+MessageId=0x0B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_FORMAT
+Language=English
+ERROR_BAD_FORMAT - An attempt was made to load a program with an incorrect format.\r
+.
+
+MessageId=0x0C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_ACCESS
+Language=English
+ERROR_INVALID_ACCESS - The access code is invalid.\r
+.
+
+MessageId=0x0D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_DATA
+Language=English
+ERROR_INVALID_DATA - The data is invalid.\r
+.
+
+MessageId=0x0E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_OUTOFMEMORY
+Language=English
+ERROR_OUTOFMEMORY - Not enough storage is available to complete this operation.\r
+.
+
+MessageId=0x0F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_DRIVE
+Language=English
+ERROR_INVALID_DRIVE - The system cannot find the drive specified.\r
+.
+
+MessageId=0x10
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CURRENT_DIRECTORY
+Language=English
+ERROR_CURRENT_DIRECTORY - The directory cannot be removed.\r
+.
+
+MessageId=0x11
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_SAME_DEVICE
+Language=English
+ERROR_NOT_SAME_DEVICE - The system cannot move the file to a different disk drive.\r
+.
+
+MessageId=0x12
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_MORE_FILES
+Language=English
+ERROR_NO_MORE_FILES - There are no more files.\r
+.
+
+MessageId=0x13
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WRITE_PROTECT
+Language=English
+ERROR_WRITE_PROTECT - The media is write protected.\r
+.
+
+MessageId=0x14
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_UNIT
+Language=English
+ERROR_BAD_UNIT - The system cannot find the device specified.\r
+.
+
+MessageId=0x15
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_READY
+Language=English
+ERROR_NOT_READY - The device is not ready.\r
+.
+
+MessageId=0x16
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_COMMAND
+Language=English
+ERROR_BAD_COMMAND - The device does not recognize the command.\r
+.
+
+MessageId=0x17
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CRC
+Language=English
+ERROR_CRC - Data error (cyclic redundancy check).\r
+.
+
+MessageId=0x18
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_LENGTH
+Language=English
+ERROR_BAD_LENGTH - The program issued a command but the command length is incorrect.\r
+.
+
+MessageId=0x19
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SEEK
+Language=English
+ERROR_SEEK - The drive cannot locate a specific area or track on the disk.\r
+.
+
+MessageId=0x1A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_DOS_DISK
+Language=English
+ERROR_NOT_DOS_DISK - The specified disk or diskette cannot be accessed.\r
+.
+
+MessageId=0x1B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SECTOR_NOT_FOUND
+Language=English
+ERROR_SECTOR_NOT_FOUND - The drive cannot find the sector requested.\r
+.
+
+MessageId=0x1C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_OUT_OF_PAPER
+Language=English
+ERROR_OUT_OF_PAPER - The printer is out of paper.\r
+.
+
+MessageId=0x1D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WRITE_FAULT
+Language=English
+ERROR_WRITE_FAULT - The system cannot write to the specified device.\r
+.
+
+MessageId=0x1E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_READ_FAULT
+Language=English
+ERROR_READ_FAULT - The system cannot read from the specified device.\r
+.
+
+MessageId=0x1F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_GEN_FAILURE
+Language=English
+ERROR_GEN_FAILURE - A device attached to the system is not functioning.\r
+.
+
+MessageId=0x20
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SHARING_VIOLATION
+Language=English
+ERROR_SHARING_VIOLATION - The process cannot access the file because it is being used by another process.\r
+.
+
+MessageId=0x21
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOCK_VIOLATION
+Language=English
+ERROR_LOCK_VIOLATION - The process cannot access the file because another process has locked a portion of the file.\r
+.
+
+MessageId=0x22
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WRONG_DISK
+Language=English
+ERROR_WRONG_DISK
+.
+
+MessageId=0x24
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SHARING_BUFFER_EXCEEDED
+Language=English
+ERROR_SHARING_BUFFER_EXCEEDED
+.
+
+MessageId=0x26
+Severity=Success
+Facility=System
+SymbolicName=ERROR_HANDLE_EOF
+Language=English
+ERROR_HANDLE_EOF - Too many files opened for sharing.\r
+.
+
+MessageId=0x27
+Severity=Success
+Facility=System
+SymbolicName=ERROR_HANDLE_DISK_FULL
+Language=English
+ERROR_HANDLE_DISK_FULL
+.
+
+MessageId=0x32
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_SUPPORTED
+Language=English
+ERROR_NOT_SUPPORTED - Reached the end of the file.\r
+.
+
+MessageId=0x33
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REM_NOT_LIST
+Language=English
+ERROR_REM_NOT_LIST - The disk is full.\r
+.
+
+MessageId=0x34
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DUP_NAME
+Language=English
+ERROR_DUP_NAME
+.
+
+MessageId=0x35
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_NETPATH
+Language=English
+ERROR_BAD_NETPATH
+.
+
+MessageId=0x36
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NETWORK_BUSY
+Language=English
+ERROR_NETWORK_BUSY
+.
+
+MessageId=0x37
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DEV_NOT_EXIST
+Language=English
+ERROR_DEV_NOT_EXIST
+.
+
+MessageId=0x38
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_CMDS
+Language=English
+ERROR_TOO_MANY_CMDS
+.
+
+MessageId=0x39
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ADAP_HDW_ERR
+Language=English
+ERROR_ADAP_HDW_ERR
+.
+
+MessageId=0x3A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_NET_RESP
+Language=English
+ERROR_BAD_NET_RESP
+.
+
+MessageId=0x3B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNEXP_NET_ERR
+Language=English
+ERROR_UNEXP_NET_ERR
+.
+
+MessageId=0x3C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_REM_ADAP
+Language=English
+ERROR_BAD_REM_ADAP
+.
+
+MessageId=0x3D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRINTQ_FULL
+Language=English
+ERROR_PRINTQ_FULL
+.
+
+MessageId=0x3E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SPOOL_SPACE
+Language=English
+ERROR_NO_SPOOL_SPACE - The network request is not supported.\r
+.
+
+MessageId=0x3F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRINT_CANCELLED
+Language=English
+ERROR_PRINT_CANCELLED - The remote computer is not available.\r
+.
+
+MessageId=0x40
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NETNAME_DELETED
+Language=English
+ERROR_NETNAME_DELETED - A duplicate name exists on the network.\r
+.
+
+MessageId=0x41
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NETWORK_ACCESS_DENIED
+Language=English
+ERROR_NETWORK_ACCESS_DENIED - The network path was not found.\r
+.
+
+MessageId=0x42
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_DEV_TYPE
+Language=English
+ERROR_BAD_DEV_TYPE - The network is busy.\r
+.
+
+MessageId=0x43
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_NET_NAME
+Language=English
+ERROR_BAD_NET_NAME - The specified network resource or device is no longer available.\r
+.
+
+MessageId=0x44
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_NAMES
+Language=English
+ERROR_TOO_MANY_NAMES - The network BIOS command limit has been reached.\r
+.
+
+MessageId=0x45
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_SESS
+Language=English
+ERROR_TOO_MANY_SESS - A network adapter hardware error occurred.\r
+.
+
+MessageId=0x46
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SHARING_PAUSED
+Language=English
+ERROR_SHARING_PAUSED - The specified server cannot perform the requested operation.\r
+.
+
+MessageId=0x47
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REQ_NOT_ACCEP
+Language=English
+ERROR_REQ_NOT_ACCEP - An unexpected network error occurred.\r
+.
+
+MessageId=0x48
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REDIR_PAUSED
+Language=English
+ERROR_REDIR_PAUSED - The remote adapter is not compatible.\r
+.
+
+MessageId=0x50
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FILE_EXISTS
+Language=English
+ERROR_FILE_EXISTS - The printer queue is full.\r
+.
+
+MessageId=0x52
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANNOT_MAKE
+Language=English
+ERROR_CANNOT_MAKE - Space to store the file waiting to be printed is not available on the server.\r
+.
+
+MessageId=0x53
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FAIL_I24
+Language=English
+ERROR_FAIL_I24 - Your file waiting to be printed was deleted.\r
+.
+
+MessageId=0x54
+Severity=Success
+Facility=System
+SymbolicName=ERROR_OUT_OF_STRUCTURES
+Language=English
+ERROR_OUT_OF_STRUCTURES - The specified network name is no longer available.\r
+.
+
+MessageId=0x55
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ALREADY_ASSIGNED
+Language=English
+ERROR_ALREADY_ASSIGNED - Network access is denied.\r
+.
+
+MessageId=0x56
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_PASSWORD
+Language=English
+ERROR_INVALID_PASSWORD - The network resource type is not correct.\r
+.
+
+MessageId=0x57
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_PARAMETER
+Language=English
+ERROR_INVALID_PARAMETER - The network name cannot be found.\r
+.
+
+MessageId=0x58
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NET_WRITE_FAULT
+Language=English
+ERROR_NET_WRITE_FAULT - The name limit for the local computer network adapter card was exceeded.\r
+.
+
+MessageId=0x59
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_PROC_SLOTS
+Language=English
+ERROR_NO_PROC_SLOTS - The network BIOS session limit was exceeded.\r
+.
+
+MessageId=0x64
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_SEMAPHORES
+Language=English
+ERROR_TOO_MANY_SEMAPHORES - The remote server has been paused or is in the process of being started.\r
+.
+
+MessageId=0x65
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EXCL_SEM_ALREADY_OWNED
+Language=English
+ERROR_EXCL_SEM_ALREADY_OWNED - No more connections can be made to this remote computer at this time because there are already as many connections as the computer can accept.\r
+.
+
+MessageId=0x66
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SEM_IS_SET
+Language=English
+ERROR_SEM_IS_SET - The specified printer or disk device has been paused.\r
+.
+
+MessageId=0x67
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_SEM_REQUESTS
+Language=English
+ERROR_TOO_MANY_SEM_REQUESTS
+.
+
+MessageId=0x68
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_AT_INTERRUPT_TIME
+Language=English
+ERROR_INVALID_AT_INTERRUPT_TIME
+.
+
+MessageId=0x69
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SEM_OWNER_DIED
+Language=English
+ERROR_SEM_OWNER_DIED
+.
+
+MessageId=0x6A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SEM_USER_LIMIT
+Language=English
+ERROR_SEM_USER_LIMIT
+.
+
+MessageId=0x6B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DISK_CHANGE
+Language=English
+ERROR_DISK_CHANGE
+.
+
+MessageId=0x6C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DRIVE_LOCKED
+Language=English
+ERROR_DRIVE_LOCKED
+.
+
+MessageId=0x6D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BROKEN_PIPE
+Language=English
+ERROR_BROKEN_PIPE
+.
+
+MessageId=0x6E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_OPEN_FAILED
+Language=English
+ERROR_OPEN_FAILED - The file exists.\r
+.
+
+MessageId=0x6F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BUFFER_OVERFLOW
+Language=English
+ERROR_BUFFER_OVERFLOW
+.
+
+MessageId=0x70
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DISK_FULL
+Language=English
+ERROR_DISK_FULL - The directory or file cannot be created.\r
+.
+
+MessageId=0x71
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_MORE_SEARCH_HANDLES
+Language=English
+ERROR_NO_MORE_SEARCH_HANDLES - Fail on INT 24.\r
+.
+
+MessageId=0x72
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_TARGET_HANDLE
+Language=English
+ERROR_INVALID_TARGET_HANDLE - Storage to process this request is not available.\r
+.
+
+MessageId=0x75
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_CATEGORY
+Language=English
+ERROR_INVALID_CATEGORY - The local device name is already in use.\r
+.
+
+MessageId=0x76
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_VERIFY_SWITCH
+Language=English
+ERROR_INVALID_VERIFY_SWITCH - The specified network password is not correct.\r
+.
+
+MessageId=0x77
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_DRIVER_LEVEL
+Language=English
+ERROR_BAD_DRIVER_LEVEL - The parameter is incorrect.\r
+.
+
+MessageId=0x78
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CALL_NOT_IMPLEMENTED
+Language=English
+ERROR_CALL_NOT_IMPLEMENTED - A write fault occurred on the network.\r
+.
+
+MessageId=0x79
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SEM_TIMEOUT
+Language=English
+ERROR_SEM_TIMEOUT - The system cannot start another process at this time.\r
+.
+
+MessageId=0x7A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INSUFFICIENT_BUFFER
+Language=English
+ERROR_INSUFFICIENT_BUFFER
+.
+
+MessageId=0x7B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_NAME
+Language=English
+ERROR_INVALID_NAME
+.
+
+MessageId=0x7C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_LEVEL
+Language=English
+ERROR_INVALID_LEVEL
+.
+
+MessageId=0x7D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_VOLUME_LABEL
+Language=English
+ERROR_NO_VOLUME_LABEL
+.
+
+MessageId=0x7E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MOD_NOT_FOUND
+Language=English
+ERROR_MOD_NOT_FOUND
+.
+
+MessageId=0x7F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PROC_NOT_FOUND
+Language=English
+ERROR_PROC_NOT_FOUND
+.
+
+MessageId=0x80
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WAIT_NO_CHILDREN
+Language=English
+ERROR_WAIT_NO_CHILDREN
+.
+
+MessageId=0x81
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CHILD_NOT_COMPLETE
+Language=English
+ERROR_CHILD_NOT_COMPLETE
+.
+
+MessageId=0x82
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DIRECT_ACCESS_HANDLE
+Language=English
+ERROR_DIRECT_ACCESS_HANDLE
+.
+
+MessageId=0x83
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NEGATIVE_SEEK
+Language=English
+ERROR_NEGATIVE_SEEK
+.
+
+MessageId=0x84
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SEEK_ON_DEVICE
+Language=English
+ERROR_SEEK_ON_DEVICE - Cannot create another system semaphore.\r
+.
+
+MessageId=0x85
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IS_JOIN_TARGET
+Language=English
+ERROR_IS_JOIN_TARGET - The exclusive semaphore is owned by another process.\r
+.
+
+MessageId=0x86
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IS_JOINED
+Language=English
+ERROR_IS_JOINED - The semaphore is set and cannot be closed.\r
+.
+
+MessageId=0x87
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IS_SUBSTED
+Language=English
+ERROR_IS_SUBSTED - The semaphore cannot be set again.\r
+.
+
+MessageId=0x88
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_JOINED
+Language=English
+ERROR_NOT_JOINED - Cannot request exclusive semaphores at interrupt time.\r
+.
+
+MessageId=0x89
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_SUBSTED
+Language=English
+ERROR_NOT_SUBSTED - The previous ownership of this semaphore has ended.\r
+.
+
+MessageId=0x8A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_JOIN_TO_JOIN
+Language=English
+ERROR_JOIN_TO_JOIN
+.
+
+MessageId=0x8B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SUBST_TO_SUBST
+Language=English
+ERROR_SUBST_TO_SUBST - The program stopped because an alternate diskette was not inserted.\r
+.
+
+MessageId=0x8C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_JOIN_TO_SUBST
+Language=English
+ERROR_JOIN_TO_SUBST - The disk is in use or locked by\r
+another process.\r
+.
+
+MessageId=0x8D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SUBST_TO_JOIN
+Language=English
+ERROR_SUBST_TO_JOIN - The pipe has been ended.\r
+.
+
+MessageId=0x8E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BUSY_DRIVE
+Language=English
+ERROR_BUSY_DRIVE - The system cannot open the\r
+device or file specified.\r
+.
+
+MessageId=0x8F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SAME_DRIVE
+Language=English
+ERROR_SAME_DRIVE - The file name is too long.\r
+.
+
+MessageId=0x90
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DIR_NOT_ROOT
+Language=English
+ERROR_DIR_NOT_ROOT - There is not enough space on the disk.\r
+.
+
+MessageId=0x91
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DIR_NOT_EMPTY
+Language=English
+ERROR_DIR_NOT_EMPTY - No more internal file identifiers available.\r
+.
+
+MessageId=0x92
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IS_SUBST_PATH
+Language=English
+ERROR_IS_SUBST_PATH - The target internal file identifier is incorrect.\r
+.
+
+MessageId=0x93
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IS_JOIN_PATH
+Language=English
+ERROR_IS_JOIN_PATH
+.
+
+MessageId=0x94
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PATH_BUSY
+Language=English
+ERROR_PATH_BUSY
+.
+
+MessageId=0x95
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IS_SUBST_TARGET
+Language=English
+ERROR_IS_SUBST_TARGET - The IOCTL call made by the application program is not correct.\r
+.
+
+MessageId=0x96
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SYSTEM_TRACE
+Language=English
+ERROR_SYSTEM_TRACE - The verify-on-write switch parameter value is not correct.\r
+.
+
+MessageId=0x97
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_EVENT_COUNT
+Language=English
+ERROR_INVALID_EVENT_COUNT - The system does not support the command requested.\r
+.
+
+MessageId=0x98
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_MUXWAITERS
+Language=English
+ERROR_TOO_MANY_MUXWAITERS - This function is not supported on this system.\r
+.
+
+MessageId=0x99
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_LIST_FORMAT
+Language=English
+ERROR_INVALID_LIST_FORMAT - The semaphore timeout period has expired.\r
+.
+
+MessageId=0x9A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LABEL_TOO_LONG
+Language=English
+ERROR_LABEL_TOO_LONG - The data area passed to a system call is too small.\r
+.
+
+MessageId=0x9B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_TCBS
+Language=English
+ERROR_TOO_MANY_TCBS - The filename, directory name, or volume label syntax is incorrect.\r
+.
+
+MessageId=0x9C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SIGNAL_REFUSED
+Language=English
+ERROR_SIGNAL_REFUSED - The system call level is not correct.\r
+.
+
+MessageId=0x9D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DISCARDED
+Language=English
+ERROR_DISCARDED - The disk has no volume label.\r
+.
+
+MessageId=0x9E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_LOCKED
+Language=English
+ERROR_NOT_LOCKED - The specified module could not be found.\r
+.
+
+MessageId=0x9F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_THREADID_ADDR
+Language=English
+ERROR_BAD_THREADID_ADDR - The specified procedure could not be found.\r
+.
+
+MessageId=0xA0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_ARGUMENTS
+Language=English
+ERROR_BAD_ARGUMENTS - There are no child processes to wait for.\r
+.
+
+MessageId=0xA1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_PATHNAME
+Language=English
+ERROR_BAD_PATHNAME
+.
+
+MessageId=0xA2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SIGNAL_PENDING
+Language=English
+ERROR_SIGNAL_PENDING - Attempt to use a file handle to an open disk partition for an operation other than raw disk I/O.\r
+.
+
+MessageId=0xA4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MAX_THRDS_REACHED
+Language=English
+ERROR_MAX_THRDS_REACHED - An attempt was made to move the file pointer before the beginning of the file.\r
+.
+
+MessageId=0xA7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOCK_FAILED
+Language=English
+ERROR_LOCK_FAILED - The file pointer cannot be set on the specified device or file.\r
+.
+
+MessageId=0xAA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BUSY
+Language=English
+ERROR_BUSY - A JOIN or SUBST command cannot be used for a drive that contains previously joined drives.\r
+.
+
+MessageId=0xAD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANCEL_VIOLATION
+Language=English
+ERROR_CANCEL_VIOLATION - An attempt was made to use a JOIN or SUBST command on a drive that has already been joined.\r
+.
+
+MessageId=0xAE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ATOMIC_LOCKS_NOT_SUPPORTED
+Language=English
+ERROR_ATOMIC_LOCKS_NOT_SUPPORTED - An attempt was made to use a JOIN or SUBST command on a drive that has already been substituted.\r
+.
+
+MessageId=0xB4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SEGMENT_NUMBER
+Language=English
+ERROR_INVALID_SEGMENT_NUMBER - The system tried to delete the JOIN of a drive that is not joined.\r
+.
+
+MessageId=0xB6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_ORDINAL
+Language=English
+ERROR_INVALID_ORDINAL - The system tried to delete the substitution of a drive that is not substituted.\r
+.
+
+MessageId=0xB7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ALREADY_EXISTS
+Language=English
+ERROR_ALREADY_EXISTS - The system tried to join a drive to a directory on a joined drive.\r
+.
+
+MessageId=0xBA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_FLAG_NUMBER
+Language=English
+ERROR_INVALID_FLAG_NUMBER - The system tried to substitute a drive to a directory on a substituted drive.\r
+.
+
+MessageId=0xBB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SEM_NOT_FOUND
+Language=English
+ERROR_SEM_NOT_FOUND - The system tried to join a drive to a directory on a substituted drive.\r
+.
+
+MessageId=0xBC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_STARTING_CODESEG
+Language=English
+ERROR_INVALID_STARTING_CODESEG - The system tried to SUBST a drive to a directory on a joined drive.\r
+.
+
+MessageId=0xBD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_STACKSEG
+Language=English
+ERROR_INVALID_STACKSEG - The system cannot perform a JOIN or SUBST at this time.\r
+.
+
+MessageId=0xBE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_MODULETYPE
+Language=English
+ERROR_INVALID_MODULETYPE - The system cannot join or substitute a drive to or for a directory on the same drive.\r
+.
+
+MessageId=0xBF
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_EXE_SIGNATURE
+Language=English
+ERROR_INVALID_EXE_SIGNATURE - The directory is not a subdirectory of the root directory.\r
+.
+
+MessageId=0xC0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EXE_MARKED_INVALID
+Language=English
+ERROR_EXE_MARKED_INVALID - The directory is not empty.\r
+.
+
+MessageId=0xC1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_EXE_FORMAT
+Language=English
+ERROR_BAD_EXE_FORMAT - The path specified is being used in a substitute.\r
+.
+
+MessageId=0xC2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ITERATED_DATA_EXCEEDS_64k
+Language=English
+ERROR_ITERATED_DATA_EXCEEDS_64k - Not enough resources are available to process this command.\r
+.
+
+MessageId=0xC3
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_MINALLOCSIZE
+Language=English
+ERROR_INVALID_MINALLOCSIZE - The path specified cannot be used at this time.\r
+.
+
+MessageId=0xC4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DYNLINK_FROM_INVALID_RING
+Language=English
+ERROR_DYNLINK_FROM_INVALID_RING - An attempt was made to join or substitute a drive for which a directory on the drive is the target of a previous substitute.\r
+.
+
+MessageId=0xC5
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IOPL_NOT_ENABLED
+Language=English
+ERROR_IOPL_NOT_ENABLED - System trace information was not specified in your CONFIG.SYS file, or tracing is disallowed.\r
+.
+
+MessageId=0xC6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SEGDPL
+Language=English
+ERROR_INVALID_SEGDPL - The number of specified semaphore events for DosMuxSemWait is not correct.\r
+.
+
+MessageId=0xC7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_AUTODATASEG_EXCEEDS_64k
+Language=English
+ERROR_AUTODATASEG_EXCEEDS_64k - DosMuxSemWait did not execute; too many semaphores are already set.\r
+.
+
+MessageId=0xC8
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RING2SEG_MUST_BE_MOVABLE
+Language=English
+ERROR_RING2SEG_MUST_BE_MOVABLE - The DosMuxSemWait list is not correct.\r
+.
+
+MessageId=0xC9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RELOC_CHAIN_XEEDS_SEGLIM
+Language=English
+ERROR_RELOC_CHAIN_XEEDS_SEGLIM - The volume label you entered exceeds the label character\r
+limit of the target file system.\r
+.
+
+MessageId=0xCA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INFLOOP_IN_RELOC_CHAIN
+Language=English
+ERROR_INFLOOP_IN_RELOC_CHAIN - Cannot create another thread.\r
+.
+
+MessageId=0xCB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ENVVAR_NOT_FOUND
+Language=English
+ERROR_ENVVAR_NOT_FOUND - The recipient process has refused the signal.\r
+.
+
+MessageId=0xCD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SIGNAL_SENT
+Language=English
+ERROR_NO_SIGNAL_SENT - The segment is already discarded and cannot be locked.\r
+.
+
+MessageId=0xCE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FILENAME_EXCED_RANGE
+Language=English
+ERROR_FILENAME_EXCED_RANGE - The segment is already unlocked.\r
+.
+
+MessageId=0xCF
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RING2_STACK_IN_USE
+Language=English
+ERROR_RING2_STACK_IN_USE - The address for the thread ID is not correct.\r
+.
+
+MessageId=0xD0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_META_EXPANSION_TOO_LONG
+Language=English
+ERROR_META_EXPANSION_TOO_LONG - The argument string passed to DosExecPgm is not correct.\r
+.
+
+MessageId=0xD1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SIGNAL_NUMBER
+Language=English
+ERROR_INVALID_SIGNAL_NUMBER - The specified path is invalid.\r
+.
+
+MessageId=0xD2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_THREAD_1_INACTIVE
+Language=English
+ERROR_THREAD_1_INACTIVE - A signal is already pending.\r
+.
+
+MessageId=0xD4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOCKED
+Language=English
+ERROR_LOCKED
+.
+
+MessageId=0xD6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_MODULES
+Language=English
+ERROR_TOO_MANY_MODULES - No more threads can be created in the system.\r
+.
+
+MessageId=0xD7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NESTING_NOT_ALLOWED
+Language=English
+ERROR_NESTING_NOT_ALLOWED
+.
+
+MessageId=0xE6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_PIPE
+Language=English
+ERROR_BAD_PIPE
+.
+
+MessageId=0xE7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PIPE_BUSY
+Language=English
+ERROR_PIPE_BUSY - Unable to lock a region of a file.\r
+.
+
+MessageId=0xE8
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_DATA
+Language=English
+ERROR_NO_DATA
+.
+
+MessageId=0xE9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PIPE_NOT_CONNECTED
+Language=English
+ERROR_PIPE_NOT_CONNECTED
+.
+
+MessageId=0xEA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MORE_DATA
+Language=English
+ERROR_MORE_DATA - The requested resource is in use.\r
+.
+
+MessageId=0xF0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_VC_DISCONNECTED
+Language=English
+ERROR_VC_DISCONNECTED
+.
+
+MessageId=0xFE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_EA_NAME
+Language=English
+ERROR_INVALID_EA_NAME
+.
+
+MessageId=0xFF
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EA_LIST_INCONSISTENT
+Language=English
+ERROR_EA_LIST_INCONSISTENT - A lock request was not outstanding for the supplied cancel region.\r
+.
+
+MessageId=0x103
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_MORE_ITEMS
+Language=English
+ERROR_NO_MORE_ITEMS - The file system does not support atomic changes to the lock type.\r
+.
+
+MessageId=0x10A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANNOT_COPY
+Language=English
+ERROR_CANNOT_COPY
+.
+
+MessageId=0x10B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DIRECTORY
+Language=English
+ERROR_DIRECTORY
+.
+
+MessageId=0x113
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EAS_DIDNT_FIT
+Language=English
+ERROR_EAS_DIDNT_FIT
+.
+
+MessageId=0x114
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EA_FILE_CORRUPT
+Language=English
+ERROR_EA_FILE_CORRUPT
+.
+
+MessageId=0x115
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EA_TABLE_FULL
+Language=English
+ERROR_EA_TABLE_FULL
+.
+
+MessageId=0x116
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_EA_HANDLE
+Language=English
+ERROR_INVALID_EA_HANDLE - The system detected a segment number that was not correct.\r
+.
+
+MessageId=0x11A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EAS_NOT_SUPPORTED
+Language=English
+ERROR_EAS_NOT_SUPPORTED
+.
+
+MessageId=0x120
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_OWNER
+Language=English
+ERROR_NOT_OWNER
+.
+
+MessageId=0x12A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_POSTS
+Language=English
+ERROR_TOO_MANY_POSTS - Cannot create a file when that file already exists.\r
+.
+
+MessageId=0x12B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PARTIAL_COPY
+Language=English
+ERROR_PARTIAL_COPY
+.
+
+MessageId=0x13D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MR_MID_NOT_FOUND
+Language=English
+ERROR_MR_MID_NOT_FOUND
+.
+
+MessageId=0x1E7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_ADDRESS
+Language=English
+ERROR_INVALID_ADDRESS - The flag passed is not correct.\r
+.
+
+MessageId=0x216
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ARITHMETIC_OVERFLOW
+Language=English
+ERROR_ARITHMETIC_OVERFLOW - The specified system semaphore name was not found.\r
+.
+
+MessageId=0x217
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PIPE_CONNECTED
+Language=English
+ERROR_PIPE_CONNECTED
+.
+
+MessageId=0x218
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PIPE_LISTENING
+Language=English
+ERROR_PIPE_LISTENING
+.
+
+MessageId=0x3E2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EA_ACCESS_DENIED
+Language=English
+ERROR_EA_ACCESS_DENIED
+.
+
+MessageId=0x3E3
+Severity=Success
+Facility=System
+SymbolicName=ERROR_OPERATION_ABORTED
+Language=English
+ERROR_OPERATION_ABORTED
+.
+
+MessageId=0x3E4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IO_INCOMPLETE
+Language=English
+ERROR_IO_INCOMPLETE
+.
+
+MessageId=0x3E5
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IO_PENDING
+Language=English
+ERROR_IO_PENDING
+.
+
+MessageId=0x3E6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOACCESS
+Language=English
+ERROR_NOACCESS
+.
+
+MessageId=0x3E7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SWAPERROR
+Language=English
+ERROR_SWAPERROR
+.
+
+MessageId=0x3E9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_STACK_OVERFLOW
+Language=English
+ERROR_STACK_OVERFLOW - The operating system cannot run this application program.\r
+.
+
+MessageId=0x3EA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_MESSAGE
+Language=English
+ERROR_INVALID_MESSAGE - The operating system is not presently configured to run this application.\r
+.
+
+MessageId=0x3EB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CAN_NOT_COMPLETE
+Language=English
+ERROR_CAN_NOT_COMPLETE
+.
+
+MessageId=0x3EC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_FLAGS
+Language=English
+ERROR_INVALID_FLAGS - The operating system cannot run this application program.\r
+.
+
+MessageId=0x3ED
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNRECOGNIZED_VOLUME
+Language=English
+ERROR_UNRECOGNIZED_VOLUME - The code segment cannot be greater than or equal to 64K.\r
+.
+
+MessageId=0x3EE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FILE_INVALID
+Language=English
+ERROR_FILE_INVALID
+.
+
+MessageId=0x3EF
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FULLSCREEN_MODE
+Language=English
+ERROR_FULLSCREEN_MODE
+.
+
+MessageId=0x3F0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_TOKEN
+Language=English
+ERROR_NO_TOKEN - The system could not find the environment\r
+option that was entered.\r
+.
+
+MessageId=0x3F1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BADDB
+Language=English
+ERROR_BADDB
+.
+
+MessageId=0x3F2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BADKEY
+Language=English
+ERROR_BADKEY - No process in the command subtree has a\r
+signal handler.\r
+.
+
+MessageId=0x3F3
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANTOPEN
+Language=English
+ERROR_CANTOPEN - The filename or extension is too long.\r
+.
+
+MessageId=0x3F4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANTREAD
+Language=English
+ERROR_CANTREAD - The ring 2 stack is in use.\r
+.
+
+MessageId=0x3F5
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANTWRITE
+Language=English
+ERROR_CANTWRITE - The global filename characters, * or ?, are entered incorrectly or too many global filename characters are specified.\r
+.
+
+MessageId=0x3F6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REGISTRY_RECOVERED
+Language=English
+ERROR_REGISTRY_RECOVERED - The signal being posted is not correct.\r
+.
+
+MessageId=0x3F7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REGISTRY_CORRUPT
+Language=English
+ERROR_REGISTRY_CORRUPT - The signal handler cannot be set.\r
+.
+
+MessageId=0x3F8
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REGISTRY_IO_FAILED
+Language=English
+ERROR_REGISTRY_IO_FAILED
+.
+
+MessageId=0x3F9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_REGISTRY_FILE
+Language=English
+ERROR_NOT_REGISTRY_FILE - The segment is locked and cannot be reallocated.\r
+.
+
+MessageId=0x3FA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_KEY_DELETED
+Language=English
+ERROR_KEY_DELETED
+.
+
+MessageId=0x3FB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_LOG_SPACE
+Language=English
+ERROR_NO_LOG_SPACE - Too many dynamic-link modules are attached to this program or dynamic-link module.\r
+.
+
+MessageId=0x3FC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_KEY_HAS_CHILDREN
+Language=English
+ERROR_KEY_HAS_CHILDREN - Cannot nest calls to LoadModule.\r
+.
+
+MessageId=0x3FD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CHILD_MUST_BE_VOLATILE
+Language=English
+ERROR_CHILD_MUST_BE_VOLATILE
+.
+
+MessageId=0x3FE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOTIFY_ENUM_DIR
+Language=English
+ERROR_NOTIFY_ENUM_DIR
+.
+
+MessageId=0x41B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DEPENDENT_SERVICES_RUNNING
+Language=English
+ERROR_DEPENDENT_SERVICES_RUNNING
+.
+
+MessageId=0x41C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SERVICE_CONTROL
+Language=English
+ERROR_INVALID_SERVICE_CONTROL
+.
+
+MessageId=0x41D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_REQUEST_TIMEOUT
+Language=English
+ERROR_SERVICE_REQUEST_TIMEOUT
+.
+
+MessageId=0x41E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_NO_THREAD
+Language=English
+ERROR_SERVICE_NO_THREAD
+.
+
+MessageId=0x41F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_DATABASE_LOCKED
+Language=English
+ERROR_SERVICE_DATABASE_LOCKED
+.
+
+MessageId=0x420
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_ALREADY_RUNNING
+Language=English
+ERROR_SERVICE_ALREADY_RUNNING
+.
+
+MessageId=0x421
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SERVICE_ACCOUNT
+Language=English
+ERROR_INVALID_SERVICE_ACCOUNT
+.
+
+MessageId=0x422
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_DISABLED
+Language=English
+ERROR_SERVICE_DISABLED
+.
+
+MessageId=0x423
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CIRCULAR_DEPENDENCY
+Language=English
+ERROR_CIRCULAR_DEPENDENCY
+.
+
+MessageId=0x424
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_DOES_NOT_EXIST
+Language=English
+ERROR_SERVICE_DOES_NOT_EXIST
+.
+
+MessageId=0x425
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_CANNOT_ACCEPT_CTRL
+Language=English
+ERROR_SERVICE_CANNOT_ACCEPT_CTRL
+.
+
+MessageId=0x426
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_NOT_ACTIVE
+Language=English
+ERROR_SERVICE_NOT_ACTIVE
+.
+
+MessageId=0x427
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
+Language=English
+ERROR_FAILED_SERVICE_CONTROLLER_CONNECT - The pipe state is invalid.\r
+.
+
+MessageId=0x428
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EXCEPTION_IN_SERVICE
+Language=English
+ERROR_EXCEPTION_IN_SERVICE - All pipe instances are busy.\r
+.
+
+MessageId=0x429
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DATABASE_DOES_NOT_EXIST
+Language=English
+ERROR_DATABASE_DOES_NOT_EXIST - The pipe is being closed.\r
+.
+
+MessageId=0x42A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_SPECIFIC_ERROR
+Language=English
+ERROR_SERVICE_SPECIFIC_ERROR - No process is on the other end of the pipe.\r
+.
+
+MessageId=0x42B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PROCESS_ABORTED
+Language=English
+ERROR_PROCESS_ABORTED - More data is available.\r
+.
+
+MessageId=0x42C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_DEPENDENCY_FAIL
+Language=English
+ERROR_SERVICE_DEPENDENCY_FAIL
+.
+
+MessageId=0x42D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_LOGON_FAILED
+Language=English
+ERROR_SERVICE_LOGON_FAILED
+.
+
+MessageId=0x42E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_START_HANG
+Language=English
+ERROR_SERVICE_START_HANG
+.
+
+MessageId=0x42F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SERVICE_LOCK
+Language=English
+ERROR_INVALID_SERVICE_LOCK
+.
+
+MessageId=0x430
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_MARKED_FOR_DELETE
+Language=English
+ERROR_SERVICE_MARKED_FOR_DELETE
+.
+
+MessageId=0x431
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_EXISTS
+Language=English
+ERROR_SERVICE_EXISTS - The session was canceled.\r
+.
+
+MessageId=0x432
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ALREADY_RUNNING_LKG
+Language=English
+ERROR_ALREADY_RUNNING_LKG
+.
+
+MessageId=0x433
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_DEPENDENCY_DELETED
+Language=English
+ERROR_SERVICE_DEPENDENCY_DELETED
+.
+
+MessageId=0x434
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BOOT_ALREADY_ACCEPTED
+Language=English
+ERROR_BOOT_ALREADY_ACCEPTED
+.
+
+MessageId=0x435
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_NEVER_STARTED
+Language=English
+ERROR_SERVICE_NEVER_STARTED
+.
+
+MessageId=0x436
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DUPLICATE_SERVICE_NAME
+Language=English
+ERROR_DUPLICATE_SERVICE_NAME
+.
+
+MessageId=0x44C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_END_OF_MEDIA
+Language=English
+ERROR_END_OF_MEDIA
+.
+
+MessageId=0x44D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FILEMARK_DETECTED
+Language=English
+ERROR_FILEMARK_DETECTED
+.
+
+MessageId=0x44E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BEGINNING_OF_MEDIA
+Language=English
+ERROR_BEGINNING_OF_MEDIA
+.
+
+MessageId=0x44F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SETMARK_DETECTED
+Language=English
+ERROR_SETMARK_DETECTED
+.
+
+MessageId=0x450
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_DATA_DETECTED
+Language=English
+ERROR_NO_DATA_DETECTED
+.
+
+MessageId=0x451
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PARTITION_FAILURE
+Language=English
+ERROR_PARTITION_FAILURE
+.
+
+MessageId=0x452
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_BLOCK_LENGTH
+Language=English
+ERROR_INVALID_BLOCK_LENGTH
+.
+
+MessageId=0x453
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DEVICE_NOT_PARTITIONED
+Language=English
+ERROR_DEVICE_NOT_PARTITIONED
+.
+
+MessageId=0x454
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNABLE_TO_LOCK_MEDIA
+Language=English
+ERROR_UNABLE_TO_LOCK_MEDIA - The specified extended attribute name was invalid.\r
+.
+
+MessageId=0x455
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNABLE_TO_UNLOAD_MEDIA
+Language=English
+ERROR_UNABLE_TO_UNLOAD_MEDIA - The extended attributes are inconsistent.\r
+.
+
+MessageId=0x456
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MEDIA_CHANGED
+Language=English
+ERROR_MEDIA_CHANGED
+.
+
+MessageId=0x457
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BUS_RESET
+Language=English
+ERROR_BUS_RESET
+.
+
+MessageId=0x458
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_MEDIA_IN_DRIVE
+Language=English
+ERROR_NO_MEDIA_IN_DRIVE - The wait operation timed out.\r
+.
+
+MessageId=0x459
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_UNICODE_TRANSLATION
+Language=English
+ERROR_NO_UNICODE_TRANSLATION - No more data is available.\r
+.
+
+MessageId=0x45A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DLL_INIT_FAILED
+Language=English
+ERROR_DLL_INIT_FAILED
+.
+
+MessageId=0x45B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SHUTDOWN_IN_PROGRESS
+Language=English
+ERROR_SHUTDOWN_IN_PROGRESS
+.
+
+MessageId=0x45C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SHUTDOWN_IN_PROGRESS
+Language=English
+ERROR_NO_SHUTDOWN_IN_PROGRESS
+.
+
+MessageId=0x45D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IO_DEVICE
+Language=English
+ERROR_IO_DEVICE
+.
+
+MessageId=0x45E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERIAL_NO_DEVICE
+Language=English
+ERROR_SERIAL_NO_DEVICE
+.
+
+MessageId=0x45F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_IRQ_BUSY
+Language=English
+ERROR_IRQ_BUSY
+.
+
+MessageId=0x460
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MORE_WRITES
+Language=English
+ERROR_MORE_WRITES - The copy functions cannot be used.\r
+.
+
+MessageId=0x461
+Severity=Success
+Facility=System
+SymbolicName=ERROR_COUNTER_TIMEOUT
+Language=English
+ERROR_COUNTER_TIMEOUT - The directory name is invalid.\r
+.
+
+MessageId=0x462
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FLOPPY_ID_MARK_NOT_FOUND
+Language=English
+ERROR_FLOPPY_ID_MARK_NOT_FOUND
+.
+
+MessageId=0x463
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FLOPPY_WRONG_CYLINDER
+Language=English
+ERROR_FLOPPY_WRONG_CYLINDER
+.
+
+MessageId=0x464
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FLOPPY_UNKNOWN_ERROR
+Language=English
+ERROR_FLOPPY_UNKNOWN_ERROR
+.
+
+MessageId=0x465
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FLOPPY_BAD_REGISTERS
+Language=English
+ERROR_FLOPPY_BAD_REGISTERS
+.
+
+MessageId=0x466
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DISK_RECALIBRATE_FAILED
+Language=English
+ERROR_DISK_RECALIBRATE_FAILED
+.
+
+MessageId=0x467
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DISK_OPERATION_FAILED
+Language=English
+ERROR_DISK_OPERATION_FAILED
+.
+
+MessageId=0x468
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DISK_RESET_FAILED
+Language=English
+ERROR_DISK_RESET_FAILED
+.
+
+MessageId=0x469
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EOM_OVERFLOW
+Language=English
+ERROR_EOM_OVERFLOW - The extended attributes did not fit in the buffer.\r
+.
+
+MessageId=0x46A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_ENOUGH_SERVER_MEMORY
+Language=English
+ERROR_NOT_ENOUGH_SERVER_MEMORY - The extended attribute file on the mounted file system is corrupt.\r
+.
+
+MessageId=0x46B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_POSSIBLE_DEADLOCK
+Language=English
+ERROR_POSSIBLE_DEADLOCK - The extended attribute table file is full.\r
+.
+
+MessageId=0x46C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MAPPED_ALIGNMENT
+Language=English
+ERROR_MAPPED_ALIGNMENT - The specified extended attribute handle is invalid.\r
+.
+
+MessageId=0x474
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SET_POWER_STATE_VETOED
+Language=English
+ERROR_SET_POWER_STATE_VETOED
+.
+
+MessageId=0x475
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SET_POWER_STATE_FAILED
+Language=English
+ERROR_SET_POWER_STATE_FAILED
+.
+
+MessageId=0x476
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_LINKS
+Language=English
+ERROR_TOO_MANY_LINKS
+.
+
+MessageId=0x47E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_OLD_WIN_VERSION
+Language=English
+ERROR_OLD_WIN_VERSION - The mounted file system does not support extended attributes.\r
+.
+
+MessageId=0x47F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_APP_WRONG_OS
+Language=English
+ERROR_APP_WRONG_OS
+.
+
+MessageId=0x480
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SINGLE_INSTANCE_APP
+Language=English
+ERROR_SINGLE_INSTANCE_APP
+.
+
+MessageId=0x481
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RMODE_APP
+Language=English
+ERROR_RMODE_APP
+.
+
+MessageId=0x482
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_DLL
+Language=English
+ERROR_INVALID_DLL
+.
+
+MessageId=0x483
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_ASSOCIATION
+Language=English
+ERROR_NO_ASSOCIATION
+.
+
+MessageId=0x484
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DDE_FAIL
+Language=English
+ERROR_DDE_FAIL - Attempt to release mutex not owned by caller.\r
+.
+
+MessageId=0x485
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DLL_NOT_FOUND
+Language=English
+ERROR_DLL_NOT_FOUND
+.
+
+MessageId=0x4B0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_DEVICE
+Language=English
+ERROR_BAD_DEVICE
+.
+
+MessageId=0x4B1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CONNECTION_UNAVAIL
+Language=English
+ERROR_CONNECTION_UNAVAIL
+.
+
+MessageId=0x4B2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DEVICE_ALREADY_REMEMBERED
+Language=English
+ERROR_DEVICE_ALREADY_REMEMBERED
+.
+
+MessageId=0x4B3
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_NET_OR_BAD_PATH
+Language=English
+ERROR_NO_NET_OR_BAD_PATH
+.
+
+MessageId=0x4B4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_PROVIDER
+Language=English
+ERROR_BAD_PROVIDER
+.
+
+MessageId=0x4B5
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANNOT_OPEN_PROFILE
+Language=English
+ERROR_CANNOT_OPEN_PROFILE
+.
+
+MessageId=0x4B6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_PROFILE
+Language=English
+ERROR_BAD_PROFILE
+.
+
+MessageId=0x4B7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_CONTAINER
+Language=English
+ERROR_NOT_CONTAINER
+.
+
+MessageId=0x4B8
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EXTENDED_ERROR
+Language=English
+ERROR_EXTENDED_ERROR - Too many posts were made to a semaphore.\r
+.
+
+MessageId=0x4B9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_GROUPNAME
+Language=English
+ERROR_INVALID_GROUPNAME - Only part of a ReadProcessMemory or WriteProcessMemory request was completed.\r
+.
+
+MessageId=0x4BA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_COMPUTERNAME
+Language=English
+ERROR_INVALID_COMPUTERNAME - The oplock request is denied.\r
+.
+
+MessageId=0x4BB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_EVENTNAME
+Language=English
+ERROR_INVALID_EVENTNAME - An invalid oplock acknowledgment was received by the system.\r
+.
+
+MessageId=0x4BC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_DOMAINNAME
+Language=English
+ERROR_INVALID_DOMAINNAME
+.
+
+MessageId=0x4BD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SERVICENAME
+Language=English
+ERROR_INVALID_SERVICENAME
+.
+
+MessageId=0x4BE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_NETNAME
+Language=English
+ERROR_INVALID_NETNAME
+.
+
+MessageId=0x4BF
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SHARENAME
+Language=English
+ERROR_INVALID_SHARENAME
+.
+
+MessageId=0x4C0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_PASSWORDNAME
+Language=English
+ERROR_INVALID_PASSWORDNAME
+.
+
+MessageId=0x4C1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_MESSAGENAME
+Language=English
+ERROR_INVALID_MESSAGENAME
+.
+
+MessageId=0x4C2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_MESSAGEDEST
+Language=English
+ERROR_INVALID_MESSAGEDEST
+.
+
+MessageId=0x4C3
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SESSION_CREDENTIAL_CONFLICT
+Language=English
+ERROR_SESSION_CREDENTIAL_CONFLICT
+.
+
+MessageId=0x4C4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REMOTE_SESSION_LIMIT_EXCEEDED
+Language=English
+ERROR_REMOTE_SESSION_LIMIT_EXCEEDED
+.
+
+MessageId=0x4C5
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DUP_DOMAINNAME
+Language=English
+ERROR_DUP_DOMAINNAME
+.
+
+MessageId=0x4C6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_NETWORK
+Language=English
+ERROR_NO_NETWORK
+.
+
+MessageId=0x4C7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANCELLED
+Language=English
+ERROR_CANCELLED
+.
+
+MessageId=0x4C8
+Severity=Success
+Facility=System
+SymbolicName=ERROR_USER_MAPPED_FILE
+Language=English
+ERROR_USER_MAPPED_FILE
+.
+
+MessageId=0x4C9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CONNECTION_REFUSED
+Language=English
+ERROR_CONNECTION_REFUSED
+.
+
+MessageId=0x4CA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_GRACEFUL_DISCONNECT
+Language=English
+ERROR_GRACEFUL_DISCONNECT
+.
+
+MessageId=0x4CB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ADDRESS_ALREADY_ASSOCIATED
+Language=English
+ERROR_ADDRESS_ALREADY_ASSOCIATED
+.
+
+MessageId=0x4CC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ADDRESS_NOT_ASSOCIATED
+Language=English
+ERROR_ADDRESS_NOT_ASSOCIATED
+.
+
+MessageId=0x4CD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CONNECTION_INVALID
+Language=English
+ERROR_CONNECTION_INVALID
+.
+
+MessageId=0x4CE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CONNECTION_ACTIVE
+Language=English
+ERROR_CONNECTION_ACTIVE
+.
+
+MessageId=0x4CF
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NETWORK_UNREACHABLE
+Language=English
+ERROR_NETWORK_UNREACHABLE
+.
+
+MessageId=0x4D0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_HOST_UNREACHABLE
+Language=English
+ERROR_HOST_UNREACHABLE
+.
+
+MessageId=0x4D1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PROTOCOL_UNREACHABLE
+Language=English
+ERROR_PROTOCOL_UNREACHABLE
+.
+
+MessageId=0x4D2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PORT_UNREACHABLE
+Language=English
+ERROR_PORT_UNREACHABLE
+.
+
+MessageId=0x4D3
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REQUEST_ABORTED
+Language=English
+ERROR_REQUEST_ABORTED
+.
+
+MessageId=0x4D4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CONNECTION_ABORTED
+Language=English
+ERROR_CONNECTION_ABORTED
+.
+
+MessageId=0x4D5
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RETRY
+Language=English
+ERROR_RETRY
+.
+
+MessageId=0x4D6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CONNECTION_COUNT_LIMIT
+Language=English
+ERROR_CONNECTION_COUNT_LIMIT
+.
+
+MessageId=0x4D7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOGIN_TIME_RESTRICTION
+Language=English
+ERROR_LOGIN_TIME_RESTRICTION
+.
+
+MessageId=0x4D8
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOGIN_WKSTA_RESTRICTION
+Language=English
+ERROR_LOGIN_WKSTA_RESTRICTION
+.
+
+MessageId=0x4D9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INCORRECT_ADDRESS
+Language=English
+ERROR_INCORRECT_ADDRESS
+.
+
+MessageId=0x4DA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ALREADY_REGISTERED
+Language=English
+ERROR_ALREADY_REGISTERED
+.
+
+MessageId=0x4DB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVICE_NOT_FOUND
+Language=English
+ERROR_SERVICE_NOT_FOUND
+.
+
+MessageId=0x4DC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_AUTHENTICATED
+Language=English
+ERROR_NOT_AUTHENTICATED
+.
+
+MessageId=0x4DD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_LOGGED_ON
+Language=English
+ERROR_NOT_LOGGED_ON
+.
+
+MessageId=0x4DE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CONTINUE
+Language=English
+ERROR_CONTINUE
+.
+
+MessageId=0x4DF
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ALREADY_INITIALIZED
+Language=English
+ERROR_ALREADY_INITIALIZED
+.
+
+MessageId=0x4E0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_MORE_DEVICES
+Language=English
+ERROR_NO_MORE_DEVICES
+.
+
+MessageId=0x514
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_ALL_ASSIGNED
+Language=English
+ERROR_NOT_ALL_ASSIGNED
+.
+
+MessageId=0x515
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SOME_NOT_MAPPED
+Language=English
+ERROR_SOME_NOT_MAPPED
+.
+
+MessageId=0x516
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_QUOTAS_FOR_ACCOUNT
+Language=English
+ERROR_NO_QUOTAS_FOR_ACCOUNT
+.
+
+MessageId=0x517
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOCAL_USER_SESSION_KEY
+Language=English
+ERROR_LOCAL_USER_SESSION_KEY
+.
+
+MessageId=0x518
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NULL_LM_PASSWORD
+Language=English
+ERROR_NULL_LM_PASSWORD
+.
+
+MessageId=0x519
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNKNOWN_REVISION
+Language=English
+ERROR_UNKNOWN_REVISION
+.
+
+MessageId=0x51A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REVISION_MISMATCH
+Language=English
+ERROR_REVISION_MISMATCH
+.
+
+MessageId=0x51B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_OWNER
+Language=English
+ERROR_INVALID_OWNER
+.
+
+MessageId=0x51C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_PRIMARY_GROUP
+Language=English
+ERROR_INVALID_PRIMARY_GROUP
+.
+
+MessageId=0x51D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_IMPERSONATION_TOKEN
+Language=English
+ERROR_NO_IMPERSONATION_TOKEN
+.
+
+MessageId=0x51E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANT_DISABLE_MANDATORY
+Language=English
+ERROR_CANT_DISABLE_MANDATORY
+.
+
+MessageId=0x51F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_LOGON_SERVERS
+Language=English
+ERROR_NO_LOGON_SERVERS
+.
+
+MessageId=0x520
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SUCH_LOGON_SESSION
+Language=English
+ERROR_NO_SUCH_LOGON_SESSION
+.
+
+MessageId=0x521
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SUCH_PRIVILEGE
+Language=English
+ERROR_NO_SUCH_PRIVILEGE
+.
+
+MessageId=0x522
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRIVILEGE_NOT_HELD
+Language=English
+ERROR_PRIVILEGE_NOT_HELD
+.
+
+MessageId=0x523
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_ACCOUNT_NAME
+Language=English
+ERROR_INVALID_ACCOUNT_NAME
+.
+
+MessageId=0x524
+Severity=Success
+Facility=System
+SymbolicName=ERROR_USER_EXISTS
+Language=English
+ERROR_USER_EXISTS
+.
+
+MessageId=0x525
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SUCH_USER
+Language=English
+ERROR_NO_SUCH_USER
+.
+
+MessageId=0x526
+Severity=Success
+Facility=System
+SymbolicName=ERROR_GROUP_EXISTS
+Language=English
+ERROR_GROUP_EXISTS
+.
+
+MessageId=0x527
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SUCH_GROUP
+Language=English
+ERROR_NO_SUCH_GROUP
+.
+
+MessageId=0x528
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MEMBER_IN_GROUP
+Language=English
+ERROR_MEMBER_IN_GROUP
+.
+
+MessageId=0x529
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MEMBER_NOT_IN_GROUP
+Language=English
+ERROR_MEMBER_NOT_IN_GROUP
+.
+
+MessageId=0x52A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LAST_ADMIN
+Language=English
+ERROR_LAST_ADMIN
+.
+
+MessageId=0x52B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WRONG_PASSWORD
+Language=English
+ERROR_WRONG_PASSWORD
+.
+
+MessageId=0x52C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ILL_FORMED_PASSWORD
+Language=English
+ERROR_ILL_FORMED_PASSWORD
+.
+
+MessageId=0x52D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PASSWORD_RESTRICTION
+Language=English
+ERROR_PASSWORD_RESTRICTION
+.
+
+MessageId=0x52E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOGON_FAILURE
+Language=English
+ERROR_LOGON_FAILURE
+.
+
+MessageId=0x52F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ACCOUNT_RESTRICTION
+Language=English
+ERROR_ACCOUNT_RESTRICTION
+.
+
+MessageId=0x530
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_LOGON_HOURS
+Language=English
+ERROR_INVALID_LOGON_HOURS
+.
+
+MessageId=0x531
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_WORKSTATION
+Language=English
+ERROR_INVALID_WORKSTATION
+.
+
+MessageId=0x532
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PASSWORD_EXPIRED
+Language=English
+ERROR_PASSWORD_EXPIRED
+.
+
+MessageId=0x533
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ACCOUNT_DISABLED
+Language=English
+ERROR_ACCOUNT_DISABLED
+.
+
+MessageId=0x534
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NONE_MAPPED
+Language=English
+ERROR_NONE_MAPPED
+.
+
+MessageId=0x535
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_LUIDS_REQUESTED
+Language=English
+ERROR_TOO_MANY_LUIDS_REQUESTED
+.
+
+MessageId=0x536
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LUIDS_EXHAUSTED
+Language=English
+ERROR_LUIDS_EXHAUSTED
+.
+
+MessageId=0x537
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SUB_AUTHORITY
+Language=English
+ERROR_INVALID_SUB_AUTHORITY
+.
+
+MessageId=0x538
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_ACL
+Language=English
+ERROR_INVALID_ACL
+.
+
+MessageId=0x539
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SID
+Language=English
+ERROR_INVALID_SID
+.
+
+MessageId=0x53A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SECURITY_DESCR
+Language=English
+ERROR_INVALID_SECURITY_DESCR
+.
+
+MessageId=0x53C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_INHERITANCE_ACL
+Language=English
+ERROR_BAD_INHERITANCE_ACL
+.
+
+MessageId=0x53D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVER_DISABLED
+Language=English
+ERROR_SERVER_DISABLED
+.
+
+MessageId=0x53E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVER_NOT_DISABLED
+Language=English
+ERROR_SERVER_NOT_DISABLED
+.
+
+MessageId=0x53F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_ID_AUTHORITY
+Language=English
+ERROR_INVALID_ID_AUTHORITY
+.
+
+MessageId=0x540
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ALLOTTED_SPACE_EXCEEDED
+Language=English
+ERROR_ALLOTTED_SPACE_EXCEEDED
+.
+
+MessageId=0x541
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_GROUP_ATTRIBUTES
+Language=English
+ERROR_INVALID_GROUP_ATTRIBUTES
+.
+
+MessageId=0x542
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_IMPERSONATION_LEVEL
+Language=English
+ERROR_BAD_IMPERSONATION_LEVEL
+.
+
+MessageId=0x543
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANT_OPEN_ANONYMOUS
+Language=English
+ERROR_CANT_OPEN_ANONYMOUS
+.
+
+MessageId=0x544
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_VALIDATION_CLASS
+Language=English
+ERROR_BAD_VALIDATION_CLASS
+.
+
+MessageId=0x545
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_TOKEN_TYPE
+Language=English
+ERROR_BAD_TOKEN_TYPE
+.
+
+MessageId=0x546
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SECURITY_ON_OBJECT
+Language=English
+ERROR_NO_SECURITY_ON_OBJECT
+.
+
+MessageId=0x547
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANT_ACCESS_DOMAIN_INFO
+Language=English
+ERROR_CANT_ACCESS_DOMAIN_INFO
+.
+
+MessageId=0x548
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SERVER_STATE
+Language=English
+ERROR_INVALID_SERVER_STATE
+.
+
+MessageId=0x549
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_DOMAIN_STATE
+Language=English
+ERROR_INVALID_DOMAIN_STATE
+.
+
+MessageId=0x54A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_DOMAIN_ROLE
+Language=English
+ERROR_INVALID_DOMAIN_ROLE
+.
+
+MessageId=0x54B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SUCH_DOMAIN
+Language=English
+ERROR_NO_SUCH_DOMAIN
+.
+
+MessageId=0x54C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DOMAIN_EXISTS
+Language=English
+ERROR_DOMAIN_EXISTS
+.
+
+MessageId=0x54D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DOMAIN_LIMIT_EXCEEDED
+Language=English
+ERROR_DOMAIN_LIMIT_EXCEEDED
+.
+
+MessageId=0x54E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INTERNAL_DB_CORRUPTION
+Language=English
+ERROR_INTERNAL_DB_CORRUPTION
+.
+
+MessageId=0x54F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INTERNAL_ERROR
+Language=English
+ERROR_INTERNAL_ERROR
+.
+
+MessageId=0x550
+Severity=Success
+Facility=System
+SymbolicName=ERROR_GENERIC_NOT_MAPPED
+Language=English
+ERROR_GENERIC_NOT_MAPPED
+.
+
+MessageId=0x551
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_DESCRIPTOR_FORMAT
+Language=English
+ERROR_BAD_DESCRIPTOR_FORMAT
+.
+
+MessageId=0x552
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_LOGON_PROCESS
+Language=English
+ERROR_NOT_LOGON_PROCESS
+.
+
+MessageId=0x553
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOGON_SESSION_EXISTS
+Language=English
+ERROR_LOGON_SESSION_EXISTS
+.
+
+MessageId=0x554
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SUCH_PACKAGE
+Language=English
+ERROR_NO_SUCH_PACKAGE
+.
+
+MessageId=0x555
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_LOGON_SESSION_STATE
+Language=English
+ERROR_BAD_LOGON_SESSION_STATE
+.
+
+MessageId=0x556
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOGON_SESSION_COLLISION
+Language=English
+ERROR_LOGON_SESSION_COLLISION
+.
+
+MessageId=0x557
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_LOGON_TYPE
+Language=English
+ERROR_INVALID_LOGON_TYPE
+.
+
+MessageId=0x558
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANNOT_IMPERSONATE
+Language=English
+ERROR_CANNOT_IMPERSONATE
+.
+
+MessageId=0x559
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RXACT_INVALID_STATE
+Language=English
+ERROR_RXACT_INVALID_STATE
+.
+
+MessageId=0x55A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RXACT_COMMIT_FAILURE
+Language=English
+ERROR_RXACT_COMMIT_FAILURE
+.
+
+MessageId=0x55B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SPECIAL_ACCOUNT
+Language=English
+ERROR_SPECIAL_ACCOUNT
+.
+
+MessageId=0x55C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SPECIAL_GROUP
+Language=English
+ERROR_SPECIAL_GROUP
+.
+
+MessageId=0x55D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SPECIAL_USER
+Language=English
+ERROR_SPECIAL_USER
+.
+
+MessageId=0x55E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MEMBERS_PRIMARY_GROUP
+Language=English
+ERROR_MEMBERS_PRIMARY_GROUP
+.
+
+MessageId=0x55F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOKEN_ALREADY_IN_USE
+Language=English
+ERROR_TOKEN_ALREADY_IN_USE
+.
+
+MessageId=0x560
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SUCH_ALIAS
+Language=English
+ERROR_NO_SUCH_ALIAS
+.
+
+MessageId=0x561
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MEMBER_NOT_IN_ALIAS
+Language=English
+ERROR_MEMBER_NOT_IN_ALIAS
+.
+
+MessageId=0x562
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MEMBER_IN_ALIAS
+Language=English
+ERROR_MEMBER_IN_ALIAS
+.
+
+MessageId=0x563
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ALIAS_EXISTS
+Language=English
+ERROR_ALIAS_EXISTS
+.
+
+MessageId=0x564
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOGON_NOT_GRANTED
+Language=English
+ERROR_LOGON_NOT_GRANTED
+.
+
+MessageId=0x565
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_SECRETS
+Language=English
+ERROR_TOO_MANY_SECRETS
+.
+
+MessageId=0x566
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SECRET_TOO_LONG
+Language=English
+ERROR_SECRET_TOO_LONG
+.
+
+MessageId=0x567
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INTERNAL_DB_ERROR
+Language=English
+ERROR_INTERNAL_DB_ERROR
+.
+
+MessageId=0x568
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_CONTEXT_IDS
+Language=English
+ERROR_TOO_MANY_CONTEXT_IDS
+.
+
+MessageId=0x569
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOGON_TYPE_NOT_GRANTED
+Language=English
+ERROR_LOGON_TYPE_NOT_GRANTED
+.
+
+MessageId=0x56A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NT_CROSS_ENCRYPTION_REQUIRED
+Language=English
+ERROR_NT_CROSS_ENCRYPTION_REQUIRED
+.
+
+MessageId=0x56B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SUCH_MEMBER
+Language=English
+ERROR_NO_SUCH_MEMBER
+.
+
+MessageId=0x56C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_MEMBER
+Language=English
+ERROR_INVALID_MEMBER
+.
+
+MessageId=0x56D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TOO_MANY_SIDS
+Language=English
+ERROR_TOO_MANY_SIDS
+.
+
+MessageId=0x56E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LM_CROSS_ENCRYPTION_REQUIRED
+Language=English
+ERROR_LM_CROSS_ENCRYPTION_REQUIRED
+.
+
+MessageId=0x56F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_INHERITANCE
+Language=English
+ERROR_NO_INHERITANCE
+.
+
+MessageId=0x570
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FILE_CORRUPT
+Language=English
+ERROR_FILE_CORRUPT
+.
+
+MessageId=0x571
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DISK_CORRUPT
+Language=English
+ERROR_DISK_CORRUPT
+.
+
+MessageId=0x572
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_USER_SESSION_KEY
+Language=English
+ERROR_NO_USER_SESSION_KEY
+.
+
+MessageId=0x573
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LICENSE_QUOTA_EXCEEDED
+Language=English
+ERROR_LICENSE_QUOTA_EXCEEDED
+.
+
+MessageId=0x578
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_WINDOW_HANDLE
+Language=English
+ERROR_INVALID_WINDOW_HANDLE
+.
+
+MessageId=0x579
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_MENU_HANDLE
+Language=English
+ERROR_INVALID_MENU_HANDLE
+.
+
+MessageId=0x57A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_CURSOR_HANDLE
+Language=English
+ERROR_INVALID_CURSOR_HANDLE
+.
+
+MessageId=0x57B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_ACCEL_HANDLE
+Language=English
+ERROR_INVALID_ACCEL_HANDLE
+.
+
+MessageId=0x57C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_HOOK_HANDLE
+Language=English
+ERROR_INVALID_HOOK_HANDLE
+.
+
+MessageId=0x57D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_DWP_HANDLE
+Language=English
+ERROR_INVALID_DWP_HANDLE
+.
+
+MessageId=0x57E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TLW_WITH_WSCHILD
+Language=English
+ERROR_TLW_WITH_WSCHILD
+.
+
+MessageId=0x57F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CANNOT_FIND_WND_CLASS
+Language=English
+ERROR_CANNOT_FIND_WND_CLASS
+.
+
+MessageId=0x580
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WINDOW_OF_OTHER_THREAD
+Language=English
+ERROR_WINDOW_OF_OTHER_THREAD
+.
+
+MessageId=0x581
+Severity=Success
+Facility=System
+SymbolicName=ERROR_HOTKEY_ALREADY_REGISTERED
+Language=English
+ERROR_HOTKEY_ALREADY_REGISTERED
+.
+
+MessageId=0x582
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CLASS_ALREADY_EXISTS
+Language=English
+ERROR_CLASS_ALREADY_EXISTS
+.
+
+MessageId=0x583
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CLASS_DOES_NOT_EXIST
+Language=English
+ERROR_CLASS_DOES_NOT_EXIST
+.
+
+MessageId=0x584
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CLASS_HAS_WINDOWS
+Language=English
+ERROR_CLASS_HAS_WINDOWS
+.
+
+MessageId=0x585
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_INDEX
+Language=English
+ERROR_INVALID_INDEX
+.
+
+MessageId=0x586
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_ICON_HANDLE
+Language=English
+ERROR_INVALID_ICON_HANDLE
+.
+
+MessageId=0x587
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRIVATE_DIALOG_INDEX
+Language=English
+ERROR_PRIVATE_DIALOG_INDEX
+.
+
+MessageId=0x588
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LISTBOX_ID_NOT_FOUND
+Language=English
+ERROR_LISTBOX_ID_NOT_FOUND
+.
+
+MessageId=0x589
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_WILDCARD_CHARACTERS
+Language=English
+ERROR_NO_WILDCARD_CHARACTERS
+.
+
+MessageId=0x58A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CLIPBOARD_NOT_OPEN
+Language=English
+ERROR_CLIPBOARD_NOT_OPEN
+.
+
+MessageId=0x58B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_HOTKEY_NOT_REGISTERED
+Language=English
+ERROR_HOTKEY_NOT_REGISTERED
+.
+
+MessageId=0x58C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WINDOW_NOT_DIALOG
+Language=English
+ERROR_WINDOW_NOT_DIALOG
+.
+
+MessageId=0x58D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CONTROL_ID_NOT_FOUND
+Language=English
+ERROR_CONTROL_ID_NOT_FOUND
+.
+
+MessageId=0x58E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_COMBOBOX_MESSAGE
+Language=English
+ERROR_INVALID_COMBOBOX_MESSAGE
+.
+
+MessageId=0x58F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WINDOW_NOT_COMBOBOX
+Language=English
+ERROR_WINDOW_NOT_COMBOBOX
+.
+
+MessageId=0x590
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_EDIT_HEIGHT
+Language=English
+ERROR_INVALID_EDIT_HEIGHT
+.
+
+MessageId=0x591
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DC_NOT_FOUND
+Language=English
+ERROR_DC_NOT_FOUND
+.
+
+MessageId=0x592
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_HOOK_FILTER
+Language=English
+ERROR_INVALID_HOOK_FILTER
+.
+
+MessageId=0x593
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_FILTER_PROC
+Language=English
+ERROR_INVALID_FILTER_PROC
+.
+
+MessageId=0x594
+Severity=Success
+Facility=System
+SymbolicName=ERROR_HOOK_NEEDS_HMOD
+Language=English
+ERROR_HOOK_NEEDS_HMOD
+.
+
+MessageId=0x595
+Severity=Success
+Facility=System
+SymbolicName=ERROR_GLOBAL_ONLY_HOOK
+Language=English
+ERROR_GLOBAL_ONLY_HOOK
+.
+
+MessageId=0x596
+Severity=Success
+Facility=System
+SymbolicName=ERROR_JOURNAL_HOOK_SET
+Language=English
+ERROR_JOURNAL_HOOK_SET
+.
+
+MessageId=0x597
+Severity=Success
+Facility=System
+SymbolicName=ERROR_HOOK_NOT_INSTALLED
+Language=English
+ERROR_HOOK_NOT_INSTALLED
+.
+
+MessageId=0x598
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_LB_MESSAGE
+Language=English
+ERROR_INVALID_LB_MESSAGE
+.
+
+MessageId=0x599
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SETCOUNT_ON_BAD_LB
+Language=English
+ERROR_SETCOUNT_ON_BAD_LB
+.
+
+MessageId=0x59A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LB_WITHOUT_TABSTOPS
+Language=English
+ERROR_LB_WITHOUT_TABSTOPS
+.
+
+MessageId=0x59B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DESTROY_OBJECT_OF_OTHER_THREAD
+Language=English
+ERROR_DESTROY_OBJECT_OF_OTHER_THREAD
+.
+
+MessageId=0x59C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CHILD_WINDOW_MENU
+Language=English
+ERROR_CHILD_WINDOW_MENU
+.
+
+MessageId=0x59D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SYSTEM_MENU
+Language=English
+ERROR_NO_SYSTEM_MENU
+.
+
+MessageId=0x59E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_MSGBOX_STYLE
+Language=English
+ERROR_INVALID_MSGBOX_STYLE
+.
+
+MessageId=0x59F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SPI_VALUE
+Language=English
+ERROR_INVALID_SPI_VALUE
+.
+
+MessageId=0x5A0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SCREEN_ALREADY_LOCKED
+Language=English
+ERROR_SCREEN_ALREADY_LOCKED
+.
+
+MessageId=0x5A1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_HWNDS_HAVE_DIFF_PARENT
+Language=English
+ERROR_HWNDS_HAVE_DIFF_PARENT
+.
+
+MessageId=0x5A2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_CHILD_WINDOW
+Language=English
+ERROR_NOT_CHILD_WINDOW
+.
+
+MessageId=0x5A3
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_GW_COMMAND
+Language=English
+ERROR_INVALID_GW_COMMAND
+.
+
+MessageId=0x5A4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_THREAD_ID
+Language=English
+ERROR_INVALID_THREAD_ID
+.
+
+MessageId=0x5A5
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NON_MDICHILD_WINDOW
+Language=English
+ERROR_NON_MDICHILD_WINDOW
+.
+
+MessageId=0x5A6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_POPUP_ALREADY_ACTIVE
+Language=English
+ERROR_POPUP_ALREADY_ACTIVE
+.
+
+MessageId=0x5A7
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SCROLLBARS
+Language=English
+ERROR_NO_SCROLLBARS
+.
+
+MessageId=0x5A8
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SCROLLBAR_RANGE
+Language=English
+ERROR_INVALID_SCROLLBAR_RANGE
+.
+
+MessageId=0x5A9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SHOWWIN_COMMAND
+Language=English
+ERROR_INVALID_SHOWWIN_COMMAND
+.
+
+MessageId=0x5AA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_SYSTEM_RESOURCES
+Language=English
+ERROR_NO_SYSTEM_RESOURCES
+.
+
+MessageId=0x5AB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NONPAGED_SYSTEM_RESOURCES
+Language=English
+ERROR_NONPAGED_SYSTEM_RESOURCES
+.
+
+MessageId=0x5AC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PAGED_SYSTEM_RESOURCES
+Language=English
+ERROR_PAGED_SYSTEM_RESOURCES
+.
+
+MessageId=0x5AD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WORKING_SET_QUOTA
+Language=English
+ERROR_WORKING_SET_QUOTA - Attempt to access invalid address.\r
+.
+
+MessageId=0x5AE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PAGEFILE_QUOTA
+Language=English
+ERROR_PAGEFILE_QUOTA
+.
+
+MessageId=0x5AF
+Severity=Success
+Facility=System
+SymbolicName=ERROR_COMMITMENT_LIMIT
+Language=English
+ERROR_COMMITMENT_LIMIT
+.
+
+MessageId=0x5B0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_MENU_ITEM_NOT_FOUND
+Language=English
+ERROR_MENU_ITEM_NOT_FOUND
+.
+
+MessageId=0x5DC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EVENTLOG_FILE_CORRUPT
+Language=English
+ERROR_EVENTLOG_FILE_CORRUPT
+.
+
+MessageId=0x5DD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EVENTLOG_CANT_START
+Language=English
+ERROR_EVENTLOG_CANT_START
+.
+
+MessageId=0x5DE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_LOG_FILE_FULL
+Language=English
+ERROR_LOG_FILE_FULL
+.
+
+MessageId=0x5DF
+Severity=Success
+Facility=System
+SymbolicName=ERROR_EVENTLOG_FILE_CHANGED
+Language=English
+ERROR_EVENTLOG_FILE_CHANGED
+.
+
+MessageId=0x6A4
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_STRING_BINDING
+Language=English
+RPC_S_INVALID_STRING_BINDING
+.
+
+MessageId=0x6A5
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_WRONG_KIND_OF_BINDING
+Language=English
+RPC_S_WRONG_KIND_OF_BINDING
+.
+
+MessageId=0x6A6
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_BINDING
+Language=English
+RPC_S_INVALID_BINDING
+.
+
+MessageId=0x6A7
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_PROTSEQ_NOT_SUPPORTED
+Language=English
+RPC_S_PROTSEQ_NOT_SUPPORTED
+.
+
+MessageId=0x6A8
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_RPC_PROTSEQ
+Language=English
+RPC_S_INVALID_RPC_PROTSEQ
+.
+
+MessageId=0x6A9
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_STRING_UUID
+Language=English
+RPC_S_INVALID_STRING_UUID
+.
+
+MessageId=0x6AA
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_ENDPOINT_FORMAT
+Language=English
+RPC_S_INVALID_ENDPOINT_FORMAT
+.
+
+MessageId=0x6AB
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_NET_ADDR
+Language=English
+RPC_S_INVALID_NET_ADDR
+.
+
+MessageId=0x6AC
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_ENDPOINT_FOUND
+Language=English
+RPC_S_NO_ENDPOINT_FOUND
+.
+
+MessageId=0x6AD
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_TIMEOUT
+Language=English
+RPC_S_INVALID_TIMEOUT
+.
+
+MessageId=0x6AE
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_OBJECT_NOT_FOUND
+Language=English
+RPC_S_OBJECT_NOT_FOUND
+.
+
+MessageId=0x6AF
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_ALREADY_REGISTERED
+Language=English
+RPC_S_ALREADY_REGISTERED
+.
+
+MessageId=0x6B0
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_TYPE_ALREADY_REGISTERED
+Language=English
+RPC_S_TYPE_ALREADY_REGISTERED
+.
+
+MessageId=0x6B1
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_ALREADY_LISTENING
+Language=English
+RPC_S_ALREADY_LISTENING
+.
+
+MessageId=0x6B2
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_PROTSEQS_REGISTERED
+Language=English
+RPC_S_NO_PROTSEQS_REGISTERED
+.
+
+MessageId=0x6B3
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NOT_LISTENING
+Language=English
+RPC_S_NOT_LISTENING
+.
+
+MessageId=0x6B4
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNKNOWN_MGR_TYPE
+Language=English
+RPC_S_UNKNOWN_MGR_TYPE
+.
+
+MessageId=0x6B5
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNKNOWN_IF
+Language=English
+RPC_S_UNKNOWN_IF
+.
+
+MessageId=0x6B6
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_BINDINGS
+Language=English
+RPC_S_NO_BINDINGS
+.
+
+MessageId=0x6B7
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_PROTSEQS
+Language=English
+RPC_S_NO_PROTSEQS
+.
+
+MessageId=0x6B8
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_CANT_CREATE_ENDPOINT
+Language=English
+RPC_S_CANT_CREATE_ENDPOINT
+.
+
+MessageId=0x6B9
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_OUT_OF_RESOURCES
+Language=English
+RPC_S_OUT_OF_RESOURCES
+.
+
+MessageId=0x6BA
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_SERVER_UNAVAILABLE
+Language=English
+RPC_S_SERVER_UNAVAILABLE
+.
+
+MessageId=0x6BB
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_SERVER_TOO_BUSY
+Language=English
+RPC_S_SERVER_TOO_BUSY
+.
+
+MessageId=0x6BC
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_NETWORK_OPTIONS
+Language=English
+RPC_S_INVALID_NETWORK_OPTIONS
+.
+
+MessageId=0x6BD
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_CALL_ACTIVE
+Language=English
+RPC_S_NO_CALL_ACTIVE
+.
+
+MessageId=0x6BE
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_CALL_FAILED
+Language=English
+RPC_S_CALL_FAILED
+.
+
+MessageId=0x6BF
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_CALL_FAILED_DNE
+Language=English
+RPC_S_CALL_FAILED_DNE
+.
+
+MessageId=0x6C0
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_PROTOCOL_ERROR
+Language=English
+RPC_S_PROTOCOL_ERROR
+.
+
+MessageId=0x6C2
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNSUPPORTED_TRANS_SYN
+Language=English
+RPC_S_UNSUPPORTED_TRANS_SYN
+.
+
+MessageId=0x6C4
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNSUPPORTED_TYPE
+Language=English
+RPC_S_UNSUPPORTED_TYPE
+.
+
+MessageId=0x6C5
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_TAG
+Language=English
+RPC_S_INVALID_TAG
+.
+
+MessageId=0x6C6
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_BOUND
+Language=English
+RPC_S_INVALID_BOUND
+.
+
+MessageId=0x6C7
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_ENTRY_NAME
+Language=English
+RPC_S_NO_ENTRY_NAME
+.
+
+MessageId=0x6C8
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_NAME_SYNTAX
+Language=English
+RPC_S_INVALID_NAME_SYNTAX
+.
+
+MessageId=0x6C9
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNSUPPORTED_NAME_SYNTAX
+Language=English
+RPC_S_UNSUPPORTED_NAME_SYNTAX
+.
+
+MessageId=0x6CB
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UUID_NO_ADDRESS
+Language=English
+RPC_S_UUID_NO_ADDRESS
+.
+
+MessageId=0x6CC
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_DUPLICATE_ENDPOINT
+Language=English
+RPC_S_DUPLICATE_ENDPOINT
+.
+
+MessageId=0x6CD
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNKNOWN_AUTHN_TYPE
+Language=English
+RPC_S_UNKNOWN_AUTHN_TYPE
+.
+
+MessageId=0x6CE
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_MAX_CALLS_TOO_SMALL
+Language=English
+RPC_S_MAX_CALLS_TOO_SMALL - Arithmetic result exceeded 32 bits.\r
+.
+
+MessageId=0x6CF
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_STRING_TOO_LONG
+Language=English
+RPC_S_STRING_TOO_LONG - There is a process on other end of the pipe.\r
+.
+
+MessageId=0x6D0
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_PROTSEQ_NOT_FOUND
+Language=English
+RPC_S_PROTSEQ_NOT_FOUND - Waiting for a process to open the other end of the pipe.\r
+.
+
+MessageId=0x6D1
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_PROCNUM_OUT_OF_RANGE
+Language=English
+RPC_S_PROCNUM_OUT_OF_RANGE
+.
+
+MessageId=0x6D2
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_BINDING_HAS_NO_AUTH
+Language=English
+RPC_S_BINDING_HAS_NO_AUTH
+.
+
+MessageId=0x6D3
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNKNOWN_AUTHN_SERVICE
+Language=English
+RPC_S_UNKNOWN_AUTHN_SERVICE
+.
+
+MessageId=0x6D4
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNKNOWN_AUTHN_LEVEL
+Language=English
+RPC_S_UNKNOWN_AUTHN_LEVEL
+.
+
+MessageId=0x6D5
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_AUTH_IDENTITY
+Language=English
+RPC_S_INVALID_AUTH_IDENTITY
+.
+
+MessageId=0x6D6
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNKNOWN_AUTHZ_SERVICE
+Language=English
+RPC_S_UNKNOWN_AUTHZ_SERVICE
+.
+
+MessageId=0x6D7
+Severity=Success
+Facility=System
+SymbolicName=EPT_S_INVALID_ENTRY
+Language=English
+EPT_S_INVALID_ENTRY
+.
+
+MessageId=0x6D8
+Severity=Success
+Facility=System
+SymbolicName=EPT_S_CANT_PERFORM_OP
+Language=English
+EPT_S_CANT_PERFORM_OP
+.
+
+MessageId=0x6D9
+Severity=Success
+Facility=System
+SymbolicName=EPT_S_NOT_REGISTERED
+Language=English
+EPT_S_NOT_REGISTERED
+.
+
+MessageId=0x6DA
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NOTHING_TO_EXPORT
+Language=English
+RPC_S_NOTHING_TO_EXPORT
+.
+
+MessageId=0x6DB
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INCOMPLETE_NAME
+Language=English
+RPC_S_INCOMPLETE_NAME
+.
+
+MessageId=0x6DC
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_VERS_OPTION
+Language=English
+RPC_S_INVALID_VERS_OPTION
+.
+
+MessageId=0x6DD
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_MORE_MEMBERS
+Language=English
+RPC_S_NO_MORE_MEMBERS
+.
+
+MessageId=0x6DE
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NOT_ALL_OBJS_UNEXPORTED
+Language=English
+RPC_S_NOT_ALL_OBJS_UNEXPORTED
+.
+
+MessageId=0x6DF
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INTERFACE_NOT_FOUND
+Language=English
+RPC_S_INTERFACE_NOT_FOUND
+.
+
+MessageId=0x6E0
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_ENTRY_ALREADY_EXISTS
+Language=English
+RPC_S_ENTRY_ALREADY_EXISTS
+.
+
+MessageId=0x6E1
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_ENTRY_NOT_FOUND
+Language=English
+RPC_S_ENTRY_NOT_FOUND
+.
+
+MessageId=0x6E2
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NAME_SERVICE_UNAVAILABLE
+Language=English
+RPC_S_NAME_SERVICE_UNAVAILABLE
+.
+
+MessageId=0x6E3
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_NAF_ID
+Language=English
+RPC_S_INVALID_NAF_ID
+.
+
+MessageId=0x6E4
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_CANNOT_SUPPORT
+Language=English
+RPC_S_CANNOT_SUPPORT
+.
+
+MessageId=0x6E5
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_CONTEXT_AVAILABLE
+Language=English
+RPC_S_NO_CONTEXT_AVAILABLE
+.
+
+MessageId=0x6E6
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INTERNAL_ERROR
+Language=English
+RPC_S_INTERNAL_ERROR
+.
+
+MessageId=0x6E7
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_ZERO_DIVIDE
+Language=English
+RPC_S_ZERO_DIVIDE
+.
+
+MessageId=0x6E8
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_ADDRESS_ERROR
+Language=English
+RPC_S_ADDRESS_ERROR
+.
+
+MessageId=0x6E9
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_FP_DIV_ZERO
+Language=English
+RPC_S_FP_DIV_ZERO
+.
+
+MessageId=0x6EA
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_FP_UNDERFLOW
+Language=English
+RPC_S_FP_UNDERFLOW
+.
+
+MessageId=0x6EB
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_FP_OVERFLOW
+Language=English
+RPC_S_FP_OVERFLOW
+.
+
+MessageId=0x6EC
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_NO_MORE_ENTRIES
+Language=English
+RPC_X_NO_MORE_ENTRIES
+.
+
+MessageId=0x6ED
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_SS_CHAR_TRANS_OPEN_FAIL
+Language=English
+RPC_X_SS_CHAR_TRANS_OPEN_FAIL
+.
+
+MessageId=0x6EE
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_SS_CHAR_TRANS_SHORT_FILE
+Language=English
+RPC_X_SS_CHAR_TRANS_SHORT_FILE
+.
+
+MessageId=0x6EF
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_SS_IN_NULL_CONTEXT
+Language=English
+RPC_X_SS_IN_NULL_CONTEXT
+.
+
+MessageId=0x6F1
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_SS_CONTEXT_DAMAGED
+Language=English
+RPC_X_SS_CONTEXT_DAMAGED
+.
+
+MessageId=0x6F2
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_SS_HANDLES_MISMATCH
+Language=English
+RPC_X_SS_HANDLES_MISMATCH
+.
+
+MessageId=0x6F3
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_SS_CANNOT_GET_CALL_HANDLE
+Language=English
+RPC_X_SS_CANNOT_GET_CALL_HANDLE
+.
+
+MessageId=0x6F4
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_NULL_REF_POINTER
+Language=English
+RPC_X_NULL_REF_POINTER
+.
+
+MessageId=0x6F5
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_ENUM_VALUE_OUT_OF_RANGE
+Language=English
+RPC_X_ENUM_VALUE_OUT_OF_RANGE
+.
+
+MessageId=0x6F6
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_BYTE_COUNT_TOO_SMALL
+Language=English
+RPC_X_BYTE_COUNT_TOO_SMALL
+.
+
+MessageId=0x6F7
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_BAD_STUB_DATA
+Language=English
+RPC_X_BAD_STUB_DATA
+.
+
+MessageId=0x6F8
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_USER_BUFFER
+Language=English
+ERROR_INVALID_USER_BUFFER
+.
+
+MessageId=0x6F9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNRECOGNIZED_MEDIA
+Language=English
+ERROR_UNRECOGNIZED_MEDIA
+.
+
+MessageId=0x6FA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_TRUST_LSA_SECRET
+Language=English
+ERROR_NO_TRUST_LSA_SECRET
+.
+
+MessageId=0x6FB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_TRUST_SAM_ACCOUNT
+Language=English
+ERROR_NO_TRUST_SAM_ACCOUNT
+.
+
+MessageId=0x6FC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TRUSTED_DOMAIN_FAILURE
+Language=English
+ERROR_TRUSTED_DOMAIN_FAILURE
+.
+
+MessageId=0x6FD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TRUSTED_RELATIONSHIP_FAILURE
+Language=English
+ERROR_TRUSTED_RELATIONSHIP_FAILURE
+.
+
+MessageId=0x6FE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TRUST_FAILURE
+Language=English
+ERROR_TRUST_FAILURE
+.
+
+MessageId=0x6FF
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_CALL_IN_PROGRESS
+Language=English
+RPC_S_CALL_IN_PROGRESS
+.
+
+MessageId=0x700
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NETLOGON_NOT_STARTED
+Language=English
+ERROR_NETLOGON_NOT_STARTED
+.
+
+MessageId=0x701
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ACCOUNT_EXPIRED
+Language=English
+ERROR_ACCOUNT_EXPIRED
+.
+
+MessageId=0x702
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REDIRECTOR_HAS_OPEN_HANDLES
+Language=English
+ERROR_REDIRECTOR_HAS_OPEN_HANDLES
+.
+
+MessageId=0x703
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRINTER_DRIVER_ALREADY_INSTALLED
+Language=English
+ERROR_PRINTER_DRIVER_ALREADY_INSTALLED
+.
+
+MessageId=0x704
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNKNOWN_PORT
+Language=English
+ERROR_UNKNOWN_PORT
+.
+
+MessageId=0x705
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNKNOWN_PRINTER_DRIVER
+Language=English
+ERROR_UNKNOWN_PRINTER_DRIVER
+.
+
+MessageId=0x706
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNKNOWN_PRINTPROCESSOR
+Language=English
+ERROR_UNKNOWN_PRINTPROCESSOR
+.
+
+MessageId=0x707
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_SEPARATOR_FILE
+Language=English
+ERROR_INVALID_SEPARATOR_FILE
+.
+
+MessageId=0x708
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_PRIORITY
+Language=English
+ERROR_INVALID_PRIORITY
+.
+
+MessageId=0x709
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_PRINTER_NAME
+Language=English
+ERROR_INVALID_PRINTER_NAME
+.
+
+MessageId=0x70A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRINTER_ALREADY_EXISTS
+Language=English
+ERROR_PRINTER_ALREADY_EXISTS
+.
+
+MessageId=0x70B
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_PRINTER_COMMAND
+Language=English
+ERROR_INVALID_PRINTER_COMMAND
+.
+
+MessageId=0x70C
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_DATATYPE
+Language=English
+ERROR_INVALID_DATATYPE
+.
+
+MessageId=0x70D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_ENVIRONMENT
+Language=English
+ERROR_INVALID_ENVIRONMENT
+.
+
+MessageId=0x70E
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_MORE_BINDINGS
+Language=English
+RPC_S_NO_MORE_BINDINGS
+.
+
+MessageId=0x70F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT
+Language=English
+ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT
+.
+
+MessageId=0x710
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT
+Language=English
+ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT
+.
+
+MessageId=0x711
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOLOGON_SERVER_TRUST_ACCOUNT
+Language=English
+ERROR_NOLOGON_SERVER_TRUST_ACCOUNT
+.
+
+MessageId=0x712
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DOMAIN_TRUST_INCONSISTENT
+Language=English
+ERROR_DOMAIN_TRUST_INCONSISTENT
+.
+
+MessageId=0x713
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SERVER_HAS_OPEN_HANDLES
+Language=English
+ERROR_SERVER_HAS_OPEN_HANDLES
+.
+
+MessageId=0x714
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RESOURCE_DATA_NOT_FOUND
+Language=English
+ERROR_RESOURCE_DATA_NOT_FOUND
+.
+
+MessageId=0x715
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RESOURCE_TYPE_NOT_FOUND
+Language=English
+ERROR_RESOURCE_TYPE_NOT_FOUND
+.
+
+MessageId=0x716
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RESOURCE_NAME_NOT_FOUND
+Language=English
+ERROR_RESOURCE_NAME_NOT_FOUND
+.
+
+MessageId=0x717
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RESOURCE_LANG_NOT_FOUND
+Language=English
+ERROR_RESOURCE_LANG_NOT_FOUND
+.
+
+MessageId=0x718
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_ENOUGH_QUOTA
+Language=English
+ERROR_NOT_ENOUGH_QUOTA
+.
+
+MessageId=0x719
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_INTERFACES
+Language=English
+RPC_S_NO_INTERFACES
+.
+
+MessageId=0x71A
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_CALL_CANCELLED
+Language=English
+RPC_S_CALL_CANCELLED
+.
+
+MessageId=0x71B
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_BINDING_INCOMPLETE
+Language=English
+RPC_S_BINDING_INCOMPLETE
+.
+
+MessageId=0x71C
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_COMM_FAILURE
+Language=English
+RPC_S_COMM_FAILURE
+.
+
+MessageId=0x71D
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UNSUPPORTED_AUTHN_LEVEL
+Language=English
+RPC_S_UNSUPPORTED_AUTHN_LEVEL
+.
+
+MessageId=0x71E
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NO_PRINC_NAME
+Language=English
+RPC_S_NO_PRINC_NAME
+.
+
+MessageId=0x71F
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NOT_RPC_ERROR
+Language=English
+RPC_S_NOT_RPC_ERROR
+.
+
+MessageId=0x720
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_UUID_LOCAL_ONLY
+Language=English
+RPC_S_UUID_LOCAL_ONLY
+.
+
+MessageId=0x721
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_SEC_PKG_ERROR
+Language=English
+RPC_S_SEC_PKG_ERROR
+.
+
+MessageId=0x722
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_NOT_CANCELLED
+Language=English
+RPC_S_NOT_CANCELLED
+.
+
+MessageId=0x723
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_INVALID_ES_ACTION
+Language=English
+RPC_X_INVALID_ES_ACTION
+.
+
+MessageId=0x724
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_WRONG_ES_VERSION
+Language=English
+RPC_X_WRONG_ES_VERSION
+.
+
+MessageId=0x725
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_WRONG_STUB_VERSION
+Language=English
+RPC_X_WRONG_STUB_VERSION
+.
+
+MessageId=0x726
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_INVALID_PIPE_OBJECT
+Language=English
+RPC_X_INVALID_PIPE_OBJECT
+.
+
+MessageId=0x727
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_WRONG_PIPE_ORDER
+Language=English
+RPC_X_WRONG_PIPE_ORDER
+.
+
+MessageId=0x728
+Severity=Success
+Facility=System
+SymbolicName=RPC_X_WRONG_PIPE_VERSION
+Language=English
+RPC_X_WRONG_PIPE_VERSION
+.
+
+MessageId=0x76A
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_GROUP_MEMBER_NOT_FOUND
+Language=English
+RPC_S_GROUP_MEMBER_NOT_FOUND
+.
+
+MessageId=0x76B
+Severity=Success
+Facility=System
+SymbolicName=EPT_S_CANT_CREATE
+Language=English
+EPT_S_CANT_CREATE
+.
+
+MessageId=0x76C
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_INVALID_OBJECT
+Language=English
+RPC_S_INVALID_OBJECT
+.
+
+MessageId=0x76D
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_TIME
+Language=English
+ERROR_INVALID_TIME
+.
+
+MessageId=0x76E
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_FORM_NAME
+Language=English
+ERROR_INVALID_FORM_NAME
+.
+
+MessageId=0x76F
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_FORM_SIZE
+Language=English
+ERROR_INVALID_FORM_SIZE
+.
+
+MessageId=0x770
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ALREADY_WAITING
+Language=English
+ERROR_ALREADY_WAITING
+.
+
+MessageId=0x771
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRINTER_DELETED
+Language=English
+ERROR_PRINTER_DELETED
+.
+
+MessageId=0x772
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_PRINTER_STATE
+Language=English
+ERROR_INVALID_PRINTER_STATE
+.
+
+MessageId=0x773
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PASSWORD_MUST_CHANGE
+Language=English
+ERROR_PASSWORD_MUST_CHANGE
+.
+
+MessageId=0x774
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DOMAIN_CONTROLLER_NOT_FOUND
+Language=English
+ERROR_DOMAIN_CONTROLLER_NOT_FOUND
+.
+
+MessageId=0x775
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ACCOUNT_LOCKED_OUT
+Language=English
+ERROR_ACCOUNT_LOCKED_OUT
+.
+
+MessageId=0x776
+Severity=Success
+Facility=System
+SymbolicName=OR_INVALID_OXID
+Language=English
+OR_INVALID_OXID
+.
+
+MessageId=0x777
+Severity=Success
+Facility=System
+SymbolicName=OR_INVALID_OID
+Language=English
+OR_INVALID_OID
+.
+
+MessageId=0x778
+Severity=Success
+Facility=System
+SymbolicName=OR_INVALID_SET
+Language=English
+OR_INVALID_SET
+.
+
+MessageId=0x779
+Severity=Success
+Facility=System
+SymbolicName=RPC_S_SEND_INCOMPLETE
+Language=English
+RPC_S_SEND_INCOMPLETE
+.
+
+MessageId=0x7D0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_PIXEL_FORMAT
+Language=English
+ERROR_INVALID_PIXEL_FORMAT
+.
+
+MessageId=0x7D1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_DRIVER
+Language=English
+ERROR_BAD_DRIVER
+.
+
+MessageId=0x7D2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INVALID_WINDOW_STYLE
+Language=English
+ERROR_INVALID_WINDOW_STYLE
+.
+
+MessageId=0x7D3
+Severity=Success
+Facility=System
+SymbolicName=ERROR_METAFILE_NOT_SUPPORTED
+Language=English
+ERROR_METAFILE_NOT_SUPPORTED
+.
+
+MessageId=0x7D4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_TRANSFORM_NOT_SUPPORTED
+Language=English
+ERROR_TRANSFORM_NOT_SUPPORTED
+.
+
+MessageId=0x7D5
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CLIPPING_NOT_SUPPORTED
+Language=English
+ERROR_CLIPPING_NOT_SUPPORTED
+.
+
+MessageId=0x89A
+Severity=Success
+Facility=System
+SymbolicName=ERROR_BAD_USERNAME
+Language=English
+ERROR_BAD_USERNAME
+.
+
+MessageId=0x8CA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NOT_CONNECTED
+Language=English
+ERROR_NOT_CONNECTED
+.
+
+MessageId=0x961
+Severity=Success
+Facility=System
+SymbolicName=ERROR_OPEN_FILES
+Language=English
+ERROR_OPEN_FILES
+.
+
+MessageId=0x962
+Severity=Success
+Facility=System
+SymbolicName=ERROR_ACTIVE_CONNECTIONS
+Language=English
+ERROR_ACTIVE_CONNECTIONS
+.
+
+MessageId=0x964
+Severity=Success
+Facility=System
+SymbolicName=ERROR_DEVICE_IN_USE
+Language=English
+ERROR_DEVICE_IN_USE
+.
+
+MessageId=0xBB8
+Severity=Success
+Facility=System
+SymbolicName=ERROR_UNKNOWN_PRINT_MONITOR
+Language=English
+ERROR_UNKNOWN_PRINT_MONITOR
+.
+
+MessageId=0xBB9
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRINTER_DRIVER_IN_USE
+Language=English
+ERROR_PRINTER_DRIVER_IN_USE
+.
+
+MessageId=0xBBA
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SPOOL_FILE_NOT_FOUND
+Language=English
+ERROR_SPOOL_FILE_NOT_FOUND
+.
+
+MessageId=0xBBB
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SPL_NO_STARTDOC
+Language=English
+ERROR_SPL_NO_STARTDOC
+.
+
+MessageId=0xBBC
+Severity=Success
+Facility=System
+SymbolicName=ERROR_SPL_NO_ADDJOB
+Language=English
+ERROR_SPL_NO_ADDJOB
+.
+
+MessageId=0xBBD
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED
+Language=English
+ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED
+.
+
+MessageId=0xBBE
+Severity=Success
+Facility=System
+SymbolicName=ERROR_PRINT_MONITOR_ALREADY_INSTALLED
+Language=English
+ERROR_PRINT_MONITOR_ALREADY_INSTALLED
+.
+
+MessageId=0xFA0
+Severity=Success
+Facility=System
+SymbolicName=ERROR_WINS_INTERNAL
+Language=English
+ERROR_WINS_INTERNAL
+.
+
+MessageId=0xFA1
+Severity=Success
+Facility=System
+SymbolicName=ERROR_CAN_NOT_DEL_LOCAL_WINS
+Language=English
+ERROR_CAN_NOT_DEL_LOCAL_WINS
+.
+
+MessageId=0xFA2
+Severity=Success
+Facility=System
+SymbolicName=ERROR_STATIC_INIT
+Language=English
+ERROR_STATIC_INIT
+.
+
+MessageId=0xFA3
+Severity=Success
+Facility=System
+SymbolicName=ERROR_INC_BACKUP
+Language=English
+ERROR_INC_BACKUP
+.
+
+MessageId=0xFA4
+Severity=Success
+Facility=System
+SymbolicName=ERROR_FULL_BACKUP
+Language=English
+ERROR_FULL_BACKUP
+.
+
+MessageId=0xFA5
+Severity=Success
+Facility=System
+SymbolicName=ERROR_REC_NON_EXISTENT
+Language=English
+ERROR_REC_NON_EXISTENT
+.
+
+MessageId=0xFA6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_RPL_NOT_ALLOWED
+Language=English
+ERROR_RPL_NOT_ALLOWED
+.
+
+MessageId=0x17E6
+Severity=Success
+Facility=System
+SymbolicName=ERROR_NO_BROWSER_SERVERS_FOUND
+Language=English
+ERROR_NO_BROWSER_SERVERS_FOUND
+.
+
+; EOF
--- /dev/null
+/* $Id$
+ *
+ * reactos/lib/kernel32/misc/errormsg.c
+ *
+ */
+/*
+ * FormatMessage implementation
+ *
+ * Copyright 1996 Marcus Meissner
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <ddk/ntddk.h>
+
+// #define NDEBUG
+#include <kernel32/kernel32.h>
+#include <kernel32/error.h>
+
+#define USE_WINE_PORT
+
+#ifdef USE_WINE_PORT
+
+//#define NDEBUG
+//#include <ntdll/ntdll.h>
+
+//#define DPRINTF DPRINT
+//#define ERR DPRINT
+//#define SetLastError(x)
+//#define WARN DPRINT
+#define TRACE DPRINT
+#define FIXME DPRINT
+
+#define strlenW lstrlen
+#define strlen lstrlen
+
+#define MAKEINTRESOURCE(i) (LPTSTR) ((DWORD) ((WORD) (i)))
+//#define MAKEINTRESOURCEA(i) (LPTSTR) ((DWORD) ((WORD) (i)))
+//#define MAKEINTRESOURCEW(i) (LPTSTR) ((DWORD) ((WORD) (i)))
+
+#define MAKEINTRESOURCEA(i) (LPSTR)((ULONG_PTR)((WORD)(i)))
+#define MAKEINTRESOURCEW(i) (LPWSTR)((ULONG_PTR)((WORD)(i)))
+//#define MAKEINTRESOURCE WINELIB_NAME_AW(MAKEINTRESOURCE)
+
+
+
+int HEAP_strdupWtoA(HANDLE hHeap, int flags, LPWSTR lpSource)
+{
+ return 0;
+}
+
+/* INTERNAL */
+
+//#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+
+//#include "windef.h"
+//#include "winbase.h"
+//#include "winerror.h"
+//#include "winuser.h"
+//#include "winnls.h"
+//#include "wine/unicode.h"
+//#include "heap.h"
+//#include "wine/debug.h"
+
+//WINE_DEFAULT_DEBUG_CHANNEL(resource);
+
+typedef struct tagMESSAGE_RESOURCE_ENTRY {
+ WORD Length;
+ WORD Flags;
+ BYTE Text[1];
+} MESSAGE_RESOURCE_ENTRY,*PMESSAGE_RESOURCE_ENTRY;
+#define MESSAGE_RESOURCE_UNICODE 0x0001
+
+typedef struct tagMESSAGE_RESOURCE_BLOCK {
+ DWORD LowId;
+ DWORD HighId;
+ DWORD OffsetToEntries;
+} MESSAGE_RESOURCE_BLOCK,*PMESSAGE_RESOURCE_BLOCK;
+
+typedef struct tagMESSAGE_RESOURCE_DATA {
+ DWORD NumberOfBlocks;
+ MESSAGE_RESOURCE_BLOCK Blocks[ 1 ];
+} MESSAGE_RESOURCE_DATA,*PMESSAGE_RESOURCE_DATA;
+
+
+//#define RT_RCDATAA MAKEINTRESOURCEA(10)
+//#define RT_RCDATAW MAKEINTRESOURCEW(10)
+////#define RT_RCDATA WINELIB_NAME_AW(RT_RCDATA)
+//#define RT_MESSAGETABLEA MAKEINTRESOURCEA(11)
+#define RT_MESSAGETABLEW MAKEINTRESOURCEW(11)
+////#define RT_MESSAGETABLE WINELIB_NAME_AW(RT_MESSAGETABLE)
+
+/* Messages...used by FormatMessage32* (KERNEL32.something)
+ *
+ * They can be specified either directly or using a message ID and
+ * loading them from the resource.
+ *
+ * The resourcedata has following format:
+ * start:
+ * 0: DWORD nrofentries
+ * nrofentries * subentry:
+ * 0: DWORD firstentry
+ * 4: DWORD lastentry
+ * 8: DWORD offset from start to the stringentries
+ *
+ * (lastentry-firstentry) * stringentry:
+ * 0: WORD len (0 marks end) [ includes the 4 byte header length ]
+ * 2: WORD flags
+ * 4: CHAR[len-4]
+ * (stringentry i of a subentry refers to the ID 'firstentry+i')
+ *
+ * Yes, ANSI strings in win32 resources. Go figure.
+ */
+
+/**********************************************************************
+ * load_messageA (internal)
+ */
+static INT load_messageA( HMODULE instance, UINT id, WORD lang,
+ LPSTR buffer, INT buflen )
+{
+ HGLOBAL hmem;
+ HRSRC hrsrc;
+ PMESSAGE_RESOURCE_DATA mrd;
+ PMESSAGE_RESOURCE_BLOCK mrb;
+ PMESSAGE_RESOURCE_ENTRY mre;
+ int i,slen;
+
+ //TRACE("instance = %08lx, id = %08lx, buffer = %p, length = %ld\n", (DWORD)instance, (DWORD)id, buffer, (DWORD)buflen);
+
+ /*FIXME: I am not sure about the '1' ... But I've only seen those entries*/
+ hrsrc = FindResourceExW(instance,RT_MESSAGETABLEW,(LPWSTR)1,lang);
+ if (!hrsrc) return 0;
+ hmem = LoadResource( instance, hrsrc );
+ if (!hmem) return 0;
+
+ mrd = (PMESSAGE_RESOURCE_DATA)LockResource(hmem);
+ mre = NULL;
+ mrb = &(mrd->Blocks[0]);
+ for (i=mrd->NumberOfBlocks;i--;) {
+ if ((id>=mrb->LowId) && (id<=mrb->HighId)) {
+ mre = (PMESSAGE_RESOURCE_ENTRY)(((char*)mrd)+mrb->OffsetToEntries);
+ id -= mrb->LowId;
+ break;
+ }
+ mrb++;
+ }
+ if (!mre)
+ return 0;
+ for (i=id;i--;) {
+ if (!mre->Length)
+ return 0;
+ mre = (PMESSAGE_RESOURCE_ENTRY)(((char*)mre)+mre->Length);
+ }
+ slen=mre->Length;
+ //TRACE(" - strlen=%d\n",slen);
+ i = min(buflen - 1, slen);
+ if (buffer == NULL)
+ return slen;
+ if (i>0) {
+ if (mre->Flags & MESSAGE_RESOURCE_UNICODE)
+ WideCharToMultiByte( CP_ACP, 0, (LPWSTR)mre->Text, -1, buffer, i, NULL, NULL );
+ else
+ lstrcpynA(buffer, (LPSTR)mre->Text, i);
+ buffer[i]=0;
+ } else {
+ if (buflen>1) {
+ buffer[0]=0;
+ return 0;
+ }
+ }
+ if (buffer) {
+ //TRACE("'%s' copied !\n", buffer);
+ TRACE("'%s'\n", buffer);
+ }
+ return i;
+}
+
+#if 0 /* FIXME */
+/**********************************************************************
+ * load_messageW (internal)
+ */
+static INT load_messageW( HMODULE instance, UINT id, WORD lang,
+ LPWSTR buffer, INT buflen )
+{
+ INT retval;
+ LPSTR buffer2 = NULL;
+ if (buffer && buflen)
+ buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen );
+ retval = load_messageA(instance,id,lang,buffer2,buflen);
+ if (buffer)
+ {
+ if (retval) {
+ lstrcpynAtoW( buffer, buffer2, buflen );
+ retval = strlenW( buffer );
+ }
+ HeapFree( GetProcessHeap(), 0, buffer2 );
+ }
+ return retval;
+}
+#endif
+
+
+/***********************************************************************
+ * FormatMessageA (KERNEL32.@)
+ * FIXME: missing wrap,
+ */
+DWORD WINAPI FormatMessageA(
+ DWORD dwFlags,
+ LPCVOID lpSource,
+ DWORD dwMessageId,
+ DWORD dwLanguageId,
+ LPSTR lpBuffer,
+ DWORD nSize,
+ va_list* _args )
+{
+ LPDWORD args=(LPDWORD)_args;
+#if defined(__i386__) || defined(__sparc__)
+/* This implementation is completely dependant on the format of the va_list on x86 CPUs */
+ LPSTR target,t;
+ DWORD talloced;
+ LPSTR from,f;
+ DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
+ BOOL eos = FALSE;
+ INT bufsize;
+ HMODULE hmodule = (HMODULE)lpSource;
+ CHAR ch;
+
+ //TRACE("(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n", dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
+ if ((dwFlags & FORMAT_MESSAGE_FROM_STRING)
+ &&((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
+ || (dwFlags & FORMAT_MESSAGE_FROM_HMODULE))) return 0;
+
+ if (width && width != FORMAT_MESSAGE_MAX_WIDTH_MASK)
+ FIXME("line wrapping (%lu) not supported.\n", width);
+ from = NULL;
+ if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
+ {
+ from = HeapAlloc( GetProcessHeap(), 0, strlen((LPSTR)lpSource)+1 );
+ strcpy( from, (LPSTR)lpSource );
+ }
+ else {
+ bufsize = 0;
+
+ if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE)
+ {
+ bufsize=load_messageA(hmodule,dwMessageId,dwLanguageId,NULL,100);
+ if ((!bufsize) && (!dwLanguageId)) {
+ bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),NULL,100);
+ if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),NULL,100);
+ if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
+ if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
+ if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NULL,100);
+ }
+ }
+ if ((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) && (!bufsize))
+ {
+ hmodule = GetModuleHandleA("kernel32");
+ bufsize=load_messageA(hmodule,dwMessageId,dwLanguageId,NULL,100);
+ if ((!bufsize) && (!dwLanguageId)) {
+ bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),NULL,100);
+ if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),NULL,100);
+ if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
+ if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
+ if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NULL,100);
+ }
+ }
+
+ if (!bufsize) {
+ SetLastError (ERROR_RESOURCE_LANG_NOT_FOUND);
+ return 0;
+ }
+
+ from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
+ load_messageA(hmodule,dwMessageId,dwLanguageId,from,bufsize+1);
+ }
+ target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
+ t = target;
+ talloced= 100;
+
+#define ADD_TO_T(c) do { \
+ *t++=c;\
+ if (t-target == talloced) {\
+ target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
+ t = target+talloced;\
+ talloced*=2;\
+ }\
+} while (0)
+
+ if (from) {
+ f=from;
+ if (dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS) {
+ while (*f && !eos)
+ ADD_TO_T(*f++);
+ }
+ else {
+ while (*f && !eos) {
+ if (*f=='%') {
+ int insertnr;
+ char *fmtstr,*x,*lastf;
+ DWORD *argliststart;
+
+ fmtstr = NULL;
+ lastf = f;
+ f++;
+ if (!*f) {
+ ADD_TO_T('%');
+ continue;
+ }
+ switch (*f) {
+ case '1':case '2':case '3':case '4':case '5':
+ case '6':case '7':case '8':case '9':
+ insertnr=*f-'0';
+ switch (f[1]) {
+ case '0':case '1':case '2':case '3':
+ case '4':case '5':case '6':case '7':
+ case '8':case '9':
+ f++;
+ insertnr=insertnr*10+*f-'0';
+ f++;
+ break;
+ default:
+ f++;
+ break;
+ }
+ if (*f=='!') {
+ f++;
+ if (NULL!=(x=strchr(f,'!'))) {
+ *x='\0';
+ fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
+ sprintf(fmtstr,"%%%s",f);
+ f=x+1;
+ } else {
+ fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
+ sprintf(fmtstr,"%%%s",f);
+ f+=strlen(f); /*at \0*/
+ }
+ } else {
+ if(!args) break;
+ fmtstr = HeapAlloc(GetProcessHeap(),0,3);
+ strcpy( fmtstr, "%s" );
+ }
+ if (args) {
+ int sz;
+ LPSTR b;
+
+ if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
+ argliststart=args+insertnr-1;
+ else
+ argliststart=(*(DWORD**)args)+insertnr-1;
+
+ /* FIXME: precision and width components are not handled correctly */
+ if ( (strcmp(fmtstr, "%ls") == 0) || (strcmp(fmtstr,"%S") == 0) ) {
+ sz = WideCharToMultiByte( CP_ACP, 0, *(WCHAR**)argliststart, -1, NULL, 0, NULL, NULL);
+ b = HeapAlloc(GetProcessHeap(), 0, sz);
+ WideCharToMultiByte( CP_ACP, 0, *(WCHAR**)argliststart, -1, b, sz, NULL, NULL);
+ } else {
+ b = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz = 1000);
+ /* CMF - This makes a BIG assumption about va_list */
+ TRACE("A BIG assumption\n");
+ //vsnprintf(b, sz, fmtstr, (va_list) argliststart);
+ }
+ for (x=b; *x; x++) ADD_TO_T(*x);
+
+ HeapFree(GetProcessHeap(),0,b);
+ } else {
+ /* NULL args - copy formatstr
+ * (probably wrong)
+ */
+ while ((lastf<f)&&(*lastf)) {
+ ADD_TO_T(*lastf++);
+ }
+ }
+ HeapFree(GetProcessHeap(),0,fmtstr);
+ break;
+ case 'n':
+ ADD_TO_T('\r');
+ ADD_TO_T('\n');
+ f++;
+ break;
+ case '0':
+ eos = TRUE;
+ f++;
+ break;
+ default:
+ ADD_TO_T(*f++);
+ break;
+ }
+ } else {
+ ch = *f;
+ f++;
+ if (ch == '\r') {
+ if (*f == '\n')
+ f++;
+ if(width)
+ ADD_TO_T(' ');
+ else
+ {
+ ADD_TO_T('\r');
+ ADD_TO_T('\n');
+ }
+ } else {
+ if (ch == '\n')
+ {
+ if(width)
+ ADD_TO_T(' ');
+ else
+ {
+ ADD_TO_T('\r');
+ ADD_TO_T('\n');
+ }
+ }
+ else
+ ADD_TO_T(ch);
+ }
+ }
+ }
+ }
+ *t='\0';
+ }
+ talloced = strlen(target)+1;
+ if (nSize && talloced<nSize) {
+ target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
+ }
+ //TRACE("-- %s\n",debugstr_a(target));
+ if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
+ *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc(GMEM_ZEROINIT,max(nSize, talloced));
+ memcpy(*(LPSTR*)lpBuffer,target,talloced);
+ } else {
+ lstrcpynA(lpBuffer,target,nSize);
+ }
+ HeapFree(GetProcessHeap(),0,target);
+ if (from) HeapFree(GetProcessHeap(),0,from);
+ //TRACE("-- returning %d\n", (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ? strlen(*(LPSTR*)lpBuffer):strlen(lpBuffer));
+ return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
+ strlen(*(LPSTR*)lpBuffer):
+ strlen(lpBuffer);
+#else
+ return 0;
+#endif /* __i386__ */
+}
+#undef ADD_TO_T
+
+
+/***********************************************************************
+ * FormatMessageW (KERNEL32.@)
+ */
+DWORD WINAPI FormatMessageW(
+ DWORD dwFlags,
+ LPCVOID lpSource,
+ DWORD dwMessageId,
+ DWORD dwLanguageId,
+ LPWSTR lpBuffer,
+ DWORD nSize,
+ va_list* _args)
+{
+ LPDWORD args=(LPDWORD)_args;
+#if defined(__i386__) || defined(__sparc__)
+/* This implementation is completely dependant on the format of the va_list on x86 CPUs */
+ LPSTR target,t;
+ DWORD talloced;
+ LPSTR from,f;
+ DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
+ BOOL eos = FALSE;
+ INT bufsize;
+ HMODULE hmodule = (HMODULE)lpSource;
+ CHAR ch;
+
+ //TRACE("(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n", dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
+ if ((dwFlags & FORMAT_MESSAGE_FROM_STRING)
+ &&((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
+ || (dwFlags & FORMAT_MESSAGE_FROM_HMODULE))) return 0;
+
+ if (width && width != FORMAT_MESSAGE_MAX_WIDTH_MASK) {
+ FIXME("line wrapping not supported.\n");
+ }
+ from = NULL;
+ if (dwFlags & FORMAT_MESSAGE_FROM_STRING) {
+ from = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lpSource);
+ }
+ else {
+ bufsize = 0;
+
+ if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE)
+ {
+ bufsize=load_messageA(hmodule,dwMessageId,dwLanguageId,NULL,100);
+ if ((!bufsize) && (!dwLanguageId)) {
+ bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),NULL,100);
+ if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),NULL,100);
+ if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
+ if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
+ if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NULL,100);
+ }
+ }
+ if ((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) && (!bufsize))
+ {
+ hmodule = GetModuleHandleA("kernel32");
+ bufsize=load_messageA(hmodule,dwMessageId,dwLanguageId,NULL,100);
+ if ((!bufsize) && (!dwLanguageId)) {
+ bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),NULL,100);
+ if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),NULL,100);
+ if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
+ if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
+ if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
+ MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NULL,100);
+ }
+ }
+
+ if (!bufsize) {
+ SetLastError (ERROR_RESOURCE_LANG_NOT_FOUND);
+ return 0;
+ }
+
+ from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
+ load_messageA(hmodule,dwMessageId,dwLanguageId,from,bufsize+1);
+ }
+ target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100 );
+ t = target;
+ talloced= 100;
+
+#define ADD_TO_T(c) do {\
+ *t++=c;\
+ if (t-target == talloced) {\
+ target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
+ t = target+talloced;\
+ talloced*=2;\
+ } \
+} while (0)
+
+ if (from) {
+ f=from;
+ if (dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS) {
+ while (*f && !eos)
+ ADD_TO_T(*f++);
+ }
+ else {
+ while (*f && !eos) {
+ if (*f=='%') {
+ int insertnr;
+ char *fmtstr,*sprintfbuf,*x;
+ DWORD *argliststart;
+
+ fmtstr = NULL;
+ f++;
+ if (!*f) {
+ ADD_TO_T('%');
+ continue;
+ }
+
+ switch (*f) {
+ case '1':case '2':case '3':case '4':case '5':
+ case '6':case '7':case '8':case '9':
+ insertnr=*f-'0';
+ switch (f[1]) {
+ case '0':case '1':case '2':case '3':
+ case '4':case '5':case '6':case '7':
+ case '8':case '9':
+ f++;
+ insertnr=insertnr*10+*f-'0';
+ f++;
+ break;
+ default:
+ f++;
+ break;
+ }
+ if (*f=='!') {
+ f++;
+ if (NULL!=(x=strchr(f,'!'))) {
+ *x='\0';
+ fmtstr=HeapAlloc( GetProcessHeap(), 0, strlen(f)+2);
+ sprintf(fmtstr,"%%%s",f);
+ f=x+1;
+ } else {
+ fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
+ sprintf(fmtstr,"%%%s",f);
+ f+=strlen(f); /*at \0*/
+ }
+ } else {
+ if(!args) break;
+ fmtstr = HeapAlloc( GetProcessHeap(),0,3);
+ strcpy( fmtstr, "%s" );
+ }
+ if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
+ argliststart=args+insertnr-1;
+ else
+ argliststart=(*(DWORD**)args)+insertnr-1;
+
+ if (fmtstr[strlen(fmtstr)-1]=='s' && argliststart[0]) {
+ DWORD xarr[3];
+
+ xarr[0]=(DWORD)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)(*(argliststart+0)));
+ /* possible invalid pointers */
+ xarr[1]=*(argliststart+1);
+ xarr[2]=*(argliststart+2);
+ sprintfbuf=HeapAlloc(GetProcessHeap(),0,strlenW((LPWSTR)argliststart[0])*2+1);
+
+ /* CMF - This makes a BIG assumption about va_list */
+ vsprintf(sprintfbuf, fmtstr, (va_list) xarr);
+ HeapFree(GetProcessHeap(), 0, (LPVOID) xarr[0]);
+ } else {
+ sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
+
+ /* CMF - This makes a BIG assumption about va_list */
+ vsprintf(sprintfbuf, fmtstr, (va_list) argliststart);
+ }
+ x=sprintfbuf;
+ while (*x) {
+ ADD_TO_T(*x++);
+ }
+ HeapFree(GetProcessHeap(),0,sprintfbuf);
+ HeapFree(GetProcessHeap(),0,fmtstr);
+ break;
+ case 'n':
+ ADD_TO_T('\r');
+ ADD_TO_T('\n');
+ f++;
+ break;
+ case '0':
+ eos = TRUE;
+ f++;
+ break;
+ default:
+ ADD_TO_T(*f++);
+ break;
+ }
+ } else {
+ ch = *f;
+ f++;
+ if (ch == '\r') {
+ if (*f == '\n')
+ f++;
+ if(width)
+ ADD_TO_T(' ');
+ else
+ {
+ ADD_TO_T('\r');
+ ADD_TO_T('\n');
+ }
+ } else {
+ if (ch == '\n')
+ {
+ if(width)
+ ADD_TO_T(' ');
+ else
+ {
+ ADD_TO_T('\r');
+ ADD_TO_T('\n');
+ }
+ }
+ else
+ ADD_TO_T(ch);
+ }
+ }
+ }
+ }
+ *t='\0';
+ }
+ talloced = strlen(target)+1;
+ if (nSize && talloced<nSize)
+ target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
+ if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
+ /* nSize is the MINIMUM size */
+ DWORD len = MultiByteToWideChar( CP_ACP, 0, target, -1, NULL, 0 );
+ *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc(GMEM_ZEROINIT,len*sizeof(WCHAR));
+ MultiByteToWideChar( CP_ACP, 0, target, -1, *(LPWSTR*)lpBuffer, len );
+ }
+ else
+ {
+ if (nSize > 0 && !MultiByteToWideChar( CP_ACP, 0, target, -1, lpBuffer, nSize ))
+ lpBuffer[nSize-1] = 0;
+ }
+ HeapFree(GetProcessHeap(),0,target);
+ if (from) HeapFree(GetProcessHeap(),0,from);
+ return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
+ strlenW(*(LPWSTR*)lpBuffer):
+ strlenW(lpBuffer);
+#else
+ return 0;
+#endif /* __i386__ */
+}
+#undef ADD_TO_T
+
+
+#else
+
+/* EXPORTED */
+
+DWORD
+STDCALL
+FormatMessageW(
+ DWORD dwFlags,
+ LPCVOID lpSource,
+ DWORD dwMessageId,
+ DWORD dwLanguageId,
+ LPWSTR lpBuffer,
+ DWORD nSize,
+ va_list* Arguments)
+{
+
+// RtlFormatMessage
+
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return 0;
+}
+
+
+DWORD
+STDCALL
+FormatMessageA(
+ DWORD dwFlags,
+ LPCVOID lpSource,
+ DWORD dwMessageId,
+ DWORD dwLanguageId,
+ LPSTR lpBuffer,
+ DWORD nSize,
+ va_list* Arguments)
+{
+ HLOCAL pBuf = NULL;
+ //LPSTR pBuf = NULL;
+
+#define MAX_MSG_STR_LEN 200
+
+ if (lpBuffer != NULL) {
+
+ if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
+ pBuf = LocalAlloc(LPTR, max(nSize, MAX_MSG_STR_LEN));
+ if (pBuf == NULL) {
+ return 0;
+ }
+ *(LPSTR*)lpBuffer = pBuf;
+ } else {
+ pBuf = *(LPSTR*)lpBuffer;
+ }
+
+ if (dwFlags & FORMAT_MESSAGE_FROM_STRING) {
+ } else {
+ }
+
+//FORMAT_MESSAGE_IGNORE_INSERTS
+//FORMAT_MESSAGE_FROM_STRING
+//FORMAT_MESSAGE_FROM_HMODULE
+//FORMAT_MESSAGE_FROM_SYSTEM
+//FORMAT_MESSAGE_ARGUMENT_ARRAY
+
+ }
+/*
+ if (FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+ 0,
+ error,
+ MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
+ (PTSTR)&msg,
+ 0,
+ NULL)
+ )
+ */
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return 0;
+}
+
+#endif
+
+/* EOF */
--- /dev/null
+/* $Id$
+ *
+ */
+#include <windows.h>
+
+
+WINBOOL
+STDCALL
+GetComputerNameW(LPWSTR lpBuffer, LPDWORD nSize)
+{
+ WCHAR Name[MAX_COMPUTERNAME_LENGTH + 1];
+ DWORD Size = 0;
+
+ /*
+ * FIXME: get the computer's name from the registry.
+ */
+ lstrcpyW(Name, L"ROSHost"); /* <-- FIXME -- */
+ Size = lstrlenW(Name) + 1;
+ if (Size > *nSize) {
+ *nSize = Size;
+ SetLastError(ERROR_BUFFER_OVERFLOW);
+ return FALSE;
+ }
+ lstrcpyW(lpBuffer, Name);
+ return TRUE;
+}
+
+
+WINBOOL
+STDCALL
+GetComputerNameA(LPSTR lpBuffer, LPDWORD nSize)
+{
+ WCHAR Name[MAX_COMPUTERNAME_LENGTH + 1];
+ int i;
+
+ if (FALSE == GetComputerNameW(Name, nSize)) {
+ return FALSE;
+ }
+
+/* FIXME --> */
+/* Use UNICODE to ANSI */
+ for (i = 0; Name[i]; ++i) {
+ lpBuffer[i] = (CHAR)Name[i];
+ }
+ lpBuffer[i] = '\0';
+/* FIXME <-- */
+
+ return TRUE;
+}
--- /dev/null
+/* $Id$
+ *
+ */
+#include <windows.h>
+
+
+/**********************************************************************
+ * NAME PRIVATE
+ * IsInstalledCP@4
+ *
+ * RETURN VALUE
+ * TRUE if CodePage is installed in the system.
+ */
+static
+BOOL
+STDCALL
+IsInstalledCP(UINT CodePage)
+{
+ /* FIXME */
+ return TRUE;
+}
+
+
+/**********************************************************************
+ * NAME EXPORTED
+ * MultiByteToWideChar@24
+ *
+ * ARGUMENTS
+ * CodePage
+ * CP_ACP ANSI code page
+ * CP_MACCP Macintosh code page
+ * CP_OEMCP OEM code page
+ * (UINT) Any installed code page
+ *
+ * dwFlags
+ * MB_PRECOMPOSED
+ * MB_COMPOSITE
+ * MB_ERR_INVALID_CHARS
+ * MB_USEGLYPHCHARS
+ *
+ * lpMultiByteStr
+ * Input buffer;
+ *
+ * cchMultiByte
+ * Size of MultiByteStr, or -1 if MultiByteStr is
+ * NULL terminated;
+ *
+ * lpWideCharStr
+ * Output buffer;
+ *
+ * cchWideChar
+ * Size (in WCHAR unit) of WideCharStr, or 0
+ * if the caller just wants to know how large
+ * WideCharStr should be for a successful
+ * conversion.
+ *
+ * RETURN VALUE
+ * 0 on error; otherwise the number of WCHAR written
+ * in the WideCharStr buffer.
+ *
+ * NOTE
+ * A raw converter for now. It assumes lpMultiByteStr is
+ * NEVER multi-byte (that is each input character is
+ * 8-bit ASCII) and is ALWAYS NULL terminated.
+ * FIXME-FIXME-FIXME-FIXME
+ */
+INT
+STDCALL
+MultiByteToWideChar(
+ UINT CodePage,
+ DWORD dwFlags,
+ LPCSTR lpMultiByteStr,
+ int cchMultiByte,
+ LPWSTR lpWideCharStr,
+ int cchWideChar)
+{
+ int InStringLength = 0;
+ PCHAR r;
+ PWCHAR w;
+ int cchConverted;
+
+ /*
+ * Check the parameters.
+ */
+ if (/* --- CODE PAGE --- */
+ ( (CP_ACP != CodePage)
+ && (CP_MACCP != CodePage)
+ && (CP_OEMCP != CodePage)
+ && (FALSE == IsInstalledCP(CodePage)) )
+ /* --- FLAGS --- */
+ || (dwFlags & ~(MB_PRECOMPOSED | MB_COMPOSITE |
+ MB_ERR_INVALID_CHARS | MB_USEGLYPHCHARS))
+ /* --- INPUT BUFFER --- */
+ || (NULL == lpMultiByteStr) )
+ {
+ SetLastError (ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+ /*
+ * Compute the input buffer length.
+ */
+ //if (-1 == cchMultiByte)
+ if (cchMultiByte < 0)
+ {
+ InStringLength = lstrlen(lpMultiByteStr) + 1;
+ }
+ else
+ {
+ InStringLength = cchMultiByte;
+ }
+ /*
+ * Does caller query for output
+ * buffer size?
+ */
+ if (0 == cchWideChar)
+ {
+ //SetLastError(ERROR_SUCCESS); /* according to wine tests this shouldn't be touched on success.
+ return InStringLength;
+ }
+ /*
+ * Is space provided for the translated
+ * string enough?
+ */
+ if (cchWideChar < InStringLength)
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return 0;
+ }
+ /*
+ * Raw 8- to 16-bit conversion.
+ */
+ for (cchConverted = 0,
+ r = (PCHAR)lpMultiByteStr,
+ w = (PWCHAR)lpWideCharStr;
+
+ cchConverted < InStringLength;
+
+ r++,
+ w++,
+ cchConverted++)
+ {
+ *w = (WCHAR)*r;
+ }
+ /*
+ * Return how many characters we
+ * wrote in the output buffer.
+ */
+ //SetLastError(ERROR_SUCCESS); /* according to wine tests this shouldn't be touched on success.
+ return cchConverted;
+}
+
+
+/**********************************************************************
+ * NAME EXPORTED
+ * WideCharToMultiByte@32
+ *
+ * Not yet implemented complete (without NLS so far)
+ *
+ * ARGUMENTS
+ * CodePage
+ * CP_ACP ANSI code page
+ * CP_MACCP Macintosh code page
+ * CP_OEMCP OEM code page
+ * CP_SYMBOL Symbol code page (42)
+ * CP_THREAD_ACP Current thread's ANSI code page
+ * CP_UTF7 Translate using UTF-7
+ * CP_UTF8 Translate using UTF-8
+ * (UINT) Any installed code page
+ *
+ * dwFlags
+ * WC_NO_BEST_FIT_CHARS
+ * WC_COMPOSITECHECK Convert composite characters to precomposed characters.
+ * WC_DISCARDNS Discard nonspacing characters during conversion.
+ * WC_SEPCHARS Generate separate characters during conversion. This is the default conversion behavior.
+ * WC_DEFAULTCHAR Replace exceptions with the default character during conversion.
+ *
+ * lpWideCharStr
+ * Points to the wide-character string to be converted.
+ *
+ * cchWideChar
+ * Size (in WCHAR unit) of WideCharStr, or 0
+ * if the caller just wants to know how large
+ * WideCharStr should be for a successful
+ * conversion.
+ * lpMultiByteStr
+ * Points to the buffer to receive the translated string.
+ * cchMultiByte
+ * Specifies the size in bytes of the buffer pointed to by the
+ * lpMultiByteStr parameter. If this value is zero, the function
+ * returns the number of bytes required for the buffer.
+ * lpDefaultChar
+ * Points to the character used if a wide character cannot be
+ * represented in the specified code page. If this parameter is
+ * NULL, a system default value is used.
+ FIXME: ignored
+ * lpUsedDefaultChar
+ * Points to a flag that indicates whether a default character was used.
+ * This parameter may be NULL.
+ FIXME: allways set to FALSE.
+ *
+ *
+ *
+ * RETURN VALUE
+ * 0 on error; otherwise the number of bytes written
+ * in the lpMultiByteStr buffer. Or the number of
+ * bytes needed for the lpMultiByteStr buffer if cchMultiByte is zero.
+ *
+ * NOTE
+ * A raw converter for now. It just cuts off the upper 9 Bit.
+ * So the MBCS-string does not contain any LeadCharacters
+ * FIXME - FIXME - FIXME - FIXME
+ */
+
+int
+STDCALL
+WideCharToMultiByte(
+ UINT CodePage,
+ DWORD dwFlags,
+ LPCWSTR lpWideCharStr,
+ int cchWideChar,
+ LPSTR lpMultiByteStr,
+ int cchMultiByte,
+ LPCSTR lpDefaultChar,
+ LPBOOL lpUsedDefaultChar
+ )
+{
+ int wi, di; // wide counter, dbcs byte count
+
+ /*
+ * Check the parameters.
+ */
+ if ( /* --- CODE PAGE --- */
+ ( (CP_ACP != CodePage)
+ && (CP_MACCP != CodePage)
+ && (CP_OEMCP != CodePage)
+ && (CP_SYMBOL != CodePage)
+ && (CP_THREAD_ACP != CodePage)
+ && (CP_UTF7 != CodePage)
+ && (CP_UTF8 != CodePage)
+ && (FALSE == IsInstalledCP (CodePage))
+ )
+ /* --- FLAGS --- */
+ || (dwFlags & ~(/*WC_NO_BEST_FIT_CHARS
+ |*/ WC_COMPOSITECHECK
+ | WC_DISCARDNS
+ | WC_SEPCHARS
+ | WC_DEFAULTCHAR
+ )
+ )
+ /* --- INPUT BUFFER --- */
+ || (NULL == lpWideCharStr)
+ )
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+
+ // for now, make no difference but only convert cut the characters to 7Bit
+ //if (cchWideChar == -1) // assume its a 0-terminated str
+ if (cchWideChar < 0) // assume its a 0-terminated str
+ { // and determine its length
+// for (cchWideChar=0; lpWideCharStr[cchWideChar]!=0; cchWideChar++)
+// cchWideChar++;
+ for (cchWideChar = 0; lpWideCharStr[cchWideChar] != 0; cchWideChar++) {
+ }
+ cchWideChar++; // length includes the null terminator
+ }
+
+ // user wants to determine needed space
+ if (cchMultiByte == 0)
+ {
+ //SetLastError(ERROR_SUCCESS); /* according to wine tests this shouldn't be touched on success.
+ return cchWideChar; // FIXME: determine correct.
+ }
+ // the lpWideCharStr is cchWideChar characters long.
+ for (wi=0, di=0; wi<cchWideChar && di<cchMultiByte; ++wi, ++di)
+ {
+ // Flag and a not displayable char FIXME
+ /*if( (dwFlags&WC_NO_BEST_FIT_CHARS) && (lpWideCharStr[wi] >127) )
+ {
+ lpMultiByteStr[di]=
+ *lpUsedDefaultChar = TRUE;
+
+ }*/
+ // FIXME
+ // just cut off the upper 9 Bit, since vals>=128 mean LeadByte.
+ lpMultiByteStr[di] = lpWideCharStr[wi] & 0x007F;
+ }
+ // has MultiByte exceeded but Wide is still in the string?
+ if (wi < cchWideChar && di >= cchMultiByte)
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return 0;
+ }
+ // else return # of bytes wirtten to MBCSbuffer (di)
+ //SetLastError(ERROR_SUCCESS); /* according to wine tests this shouldn't be touched on success.
+ // FIXME: move that elsewhere
+ if (lpUsedDefaultChar != NULL) *lpUsedDefaultChar = FALSE;
+ return di;
+}
+
+/* EOF */
--- /dev/null
+/* $Id$
+ *
+ */
+#include <windows.h>
+
+
+/***********************************************************************
+ * MulDiv (KERNEL32.@)
+ * RETURNS
+ * Result of multiplication and division
+ * -1: Overflow occurred or Divisor was 0
+ */
+
+//FIXME! move to correct file
+INT STDCALL MulDiv(
+ INT nMultiplicand,
+ INT nMultiplier,
+ INT nDivisor)
+{
+#if SIZEOF_LONG_LONG >= 8
+ long long ret;
+
+ if (!nDivisor) return -1;
+
+ /* We want to deal with a positive divisor to simplify the logic. */
+ if (nDivisor < 0)
+ {
+ nMultiplicand = - nMultiplicand;
+ nDivisor = -nDivisor;
+ }
+
+ /* If the result is positive, we "add" to round. else, we subtract to round. */
+ if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
+ ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
+ ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
+ else
+ ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
+
+ if ((ret > 2147483647) || (ret < -2147483647)) return -1;
+ return ret;
+#else
+ if (!nDivisor) return -1;
+
+ /* We want to deal with a positive divisor to simplify the logic. */
+ if (nDivisor < 0)
+ {
+ nMultiplicand = - nMultiplicand;
+ nDivisor = -nDivisor;
+ }
+
+ /* If the result is positive, we "add" to round. else, we subtract to round. */
+ if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) ||
+ ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
+ return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
+
+ return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
+
+#endif
+}
+
+
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$ */
+/*
+ * PROJECT: ReactOS system libraries
+ * FILE: lib/kernel32/misc/perfcnt.c
+ * PURPOSE: Performance counter
+ * PROGRAMMER: Eric Kohl
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <k32.h>
+
+#define NDEBUG
+#include <kernel32/kernel32.h>
+
+
+/* FUNCTIONS ****************************************************************/
+
+WINBOOL STDCALL
+QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount)
+{
+ LARGE_INTEGER Frequency;
+ NTSTATUS Status;
+
+ Status = NtQueryPerformanceCounter(lpPerformanceCount,
+ &Frequency);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return(FALSE);
+ }
+
+ if (Frequency.QuadPart == 0ULL)
+ {
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+
+WINBOOL STDCALL
+QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency)
+{
+ LARGE_INTEGER Count;
+ NTSTATUS Status;
+
+ Status = NtQueryPerformanceCounter(&Count,
+ lpFrequency);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return(FALSE);
+ }
+
+ if (lpFrequency->QuadPart == 0ULL)
+ {
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+/* EOF */
--- /dev/null
+/* $Id$
+ *
+ * KERNEL32.DLL toolhelp functions
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS system libraries
+ * FILE: lib/kernel32/misc/toolhelp.c
+ * PURPOSE: Toolhelp functions
+ * PROGRAMMER: Robert Dickenson (robd@mok.lvcm.com)
+ * UPDATE HISTORY:
+ * Created 05 January 2003
+ */
+
+#include <windows.h>
+#include <tlhelp32.h>
+
+
+#define CHECK_PARAM_SIZE(ptr, siz) \
+ if (!ptr || ptr->dwSize != siz) { \
+ SetLastError(ERROR_INVALID_PARAMETER); \
+ return FALSE; \
+ }
+
+
+BOOL WINAPI
+Heap32First(LPHEAPENTRY32 lphe, DWORD th32ProcessID, DWORD th32HeapID)
+{
+ CHECK_PARAM_SIZE(lphe, sizeof(HEAPENTRY32));
+
+ SetLastError(ERROR_NO_MORE_FILES);
+ return FALSE;
+}
+
+BOOL WINAPI
+Heap32Next(LPHEAPENTRY32 lphe)
+{
+/*
+typedef struct tagHEAPENTRY32 {
+ DWORD dwSize;
+ HANDLE hHandle;
+ DWORD dwAddress;
+ DWORD dwBlockSize;
+ DWORD dwFlags;
+ DWORD dwLockCount;
+ DWORD dwResvd;
+ DWORD th32ProcessID;
+ DWORD th32HeapID;
+} HEAPENTRY32,*PHEAPENTRY32,*LPHEAPENTRY32;
+ */
+ SetLastError(ERROR_NO_MORE_FILES);
+ return FALSE;
+}
+
+BOOL WINAPI
+Heap32ListFirst(HANDLE hSnapshot, LPHEAPLIST32 lphl)
+{
+ CHECK_PARAM_SIZE(lphl, sizeof(HEAPLIST32));
+
+ SetLastError(ERROR_NO_MORE_FILES);
+ return FALSE;
+}
+
+BOOL WINAPI
+Heap32ListNext(HANDLE hSnapshot, LPHEAPLIST32 lph1)
+{
+/*
+typedef struct tagHEAPLIST32 {
+ DWORD dwSize;
+ DWORD th32ProcessID;
+ DWORD th32HeapID;
+ DWORD dwFlags;
+} HEAPLIST32,*PHEAPLIST32,*LPHEAPLIST32;
+ */
+ SetLastError(ERROR_NO_MORE_FILES);
+ return FALSE;
+}
+
+BOOL WINAPI
+Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
+{
+ CHECK_PARAM_SIZE(lpme, sizeof(MODULEENTRY32));
+
+ SetLastError(ERROR_NO_MORE_FILES);
+ return FALSE;
+}
+
+BOOL WINAPI
+Module32FirstW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
+{
+ CHECK_PARAM_SIZE(lpme, sizeof(MODULEENTRY32W));
+
+ SetLastError(ERROR_NO_MORE_FILES);
+ return FALSE;
+}
+
+BOOL WINAPI
+Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme)
+{
+/*
+typedef struct tagMODULEENTRY32 {
+ DWORD dwSize;
+ DWORD th32ModuleID;
+ DWORD th32ProcessID;
+ DWORD GlblcntUsage;
+ DWORD ProccntUsage;
+ BYTE *modBaseAddr;
+ DWORD modBaseSize;
+ HMODULE hModule;
+ char szModule[MAX_MODULE_NAME32 + 1];
+ char szExePath[MAX_PATH];
+} MODULEENTRY32,*PMODULEENTRY32,*LPMODULEENTRY32;
+ */
+ SetLastError(ERROR_NO_MORE_FILES);
+ return FALSE;
+}
+
+BOOL WINAPI
+Module32NextW(HANDLE hSnapshot, LPMODULEENTRY32W lpme)
+{
+/*
+typedef struct tagMODULEENTRY32W {
+ DWORD dwSize;
+ DWORD th32ModuleID;
+ DWORD th32ProcessID;
+ DWORD GlblcntUsage;
+ DWORD ProccntUsage;
+ BYTE *modBaseAddr;
+ DWORD modBaseSize;
+ HMODULE hModule;
+ WCHAR szModule[MAX_MODULE_NAME32 + 1];
+ WCHAR szExePath[MAX_PATH];
+} MODULEENTRY32W,*PMODULEENTRY32W,*LPMODULEENTRY32W;
+
+ */
+ SetLastError(ERROR_NO_MORE_FILES);
+ return FALSE;
+}
+
+BOOL STDCALL
+Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
+{
+ CHECK_PARAM_SIZE(lppe, sizeof(PROCESSENTRY32));
+
+ SetLastError(ERROR_NO_MORE_FILES);
+ return FALSE;
+}
+
+BOOL STDCALL
+Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
+{
+/*
+typedef struct tagPROCESSENTRY32 {
+ DWORD dwSize;
+ DWORD cntUsage;
+ DWORD th32ProcessID;
+ DWORD th32DefaultHeapID;
+ DWORD th32ModuleID;
+ DWORD cntThreads;
+ DWORD th32ParentProcessID;
+ LONG pcPriClassBase;
+ DWORD dwFlags;
+ CHAR szExeFile[MAX_PATH];
+} PROCESSENTRY32,*PPROCESSENTRY32,*LPPROCESSENTRY32;
+ */
+ SetLastError(ERROR_NO_MORE_FILES);
+ return FALSE;
+}
+
+BOOL STDCALL
+Process32FirstW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
+{
+ CHECK_PARAM_SIZE(lppe, sizeof(PROCESSENTRY32W));
+
+ SetLastError(ERROR_NO_MORE_FILES);
+ return FALSE;
+}
+
+BOOL STDCALL
+Process32NextW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe)
+{
+/*
+typedef struct tagPROCESSENTRY32W {
+ DWORD dwSize;
+ DWORD cntUsage;
+ DWORD th32ProcessID;
+ DWORD th32DefaultHeapID;
+ DWORD th32ModuleID;
+ DWORD cntThreads;
+ DWORD th32ParentProcessID;
+ LONG pcPriClassBase;
+ DWORD dwFlags;
+ WCHAR szExeFile[MAX_PATH];
+} PROCESSENTRY32W,*PPROCESSENTRY32W,*LPPROCESSENTRY32W;
+ */
+ SetLastError(ERROR_NO_MORE_FILES);
+ return FALSE;
+}
+
+
+BOOL WINAPI Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
+{
+ CHECK_PARAM_SIZE(lpte, sizeof(THREADENTRY32));
+
+ SetLastError(ERROR_NO_MORE_FILES);
+ return FALSE;
+}
+
+BOOL WINAPI Thread32Next(HANDLE hSnapshot, LPTHREADENTRY32 lpte)
+{
+/*
+typedef struct tagTHREADENTRY32 {
+ DWORD dwSize;
+ DWORD cntUsage;
+ DWORD th32ThreadID;
+ DWORD th32OwnerProcessID;
+ LONG tpBasePri;
+ LONG tpDeltaPri;
+ DWORD dwFlags;
+} THREADENTRY32,*PTHREADENTRY32,*LPTHREADENTRY32;
+ */
+ SetLastError(ERROR_NO_MORE_FILES);
+ return FALSE;
+}
+
+BOOL WINAPI
+Toolhelp32ReadProcessMemory(DWORD th32ProcessID,
+ LPCVOID lpBaseAddress, LPVOID lpBuffer,
+ DWORD cbRead, LPDWORD lpNumberOfBytesRead)
+{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+
+#define TL_DEV_NAME L"\\??\\TlHelpDevice"
+
+HANDLE STDCALL
+CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID)
+{
+ // return open handle to snapshot on success, -1 on failure
+ // the snapshot handle behavies like an object handle
+ SECURITY_ATTRIBUTES sa;
+ HANDLE hSnapshot = (HANDLE)-1;
+
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+
+ if (dwFlags & TH32CS_INHERIT) {
+ }
+ if (dwFlags & TH32CS_SNAPHEAPLIST) {
+ }
+ if (dwFlags & TH32CS_SNAPMODULE) {
+ }
+ if (dwFlags & TH32CS_SNAPPROCESS) {
+ }
+ if (dwFlags & TH32CS_SNAPTHREAD) {
+ }
+ hSnapshot = CreateFileW(TL_DEV_NAME,
+ GENERIC_READ, FILE_SHARE_READ + FILE_SHARE_WRITE,
+ &sa, OPEN_EXISTING, 0L/*FILE_ATTRIBUTE_SYSTEM*/, 0);
+ if (hSnapshot != INVALID_HANDLE_VALUE) {
+
+ }
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+
+ // caller must use CloseHandle to destroy the returned snapshot handle
+ return hSnapshot;
+}
+
+
+#if 0 /* extracted from mingw tlhelp32.h for easy reference while working above */
+/*
+#define HF32_DEFAULT 1
+#define HF32_SHARED 2
+#define LF32_FIXED 0x1
+#define LF32_FREE 0x2
+#define LF32_MOVEABLE 0x4
+#define MAX_MODULE_NAME32 255
+#define TH32CS_SNAPHEAPLIST 0x1
+#define TH32CS_SNAPPROCESS 0x2
+#define TH32CS_SNAPTHREAD 0x4
+#define TH32CS_SNAPMODULE 0x8
+#define TH32CS_SNAPALL (TH32CS_SNAPHEAPLIST|TH32CS_SNAPPROCESS|TH32CS_SNAPTHREAD|TH32CS_SNAPMODULE)
+#define TH32CS_INHERIT 0x80000000
+
+BOOL WINAPI Heap32First(LPHEAPENTRY32,DWORD,DWORD);
+BOOL WINAPI Heap32ListFirst(HANDLE,LPHEAPLIST32);
+BOOL WINAPI Heap32ListNext(HANDLE,LPHEAPLIST32);
+BOOL WINAPI Heap32Next(LPHEAPENTRY32);
+BOOL WINAPI Module32First(HANDLE,LPMODULEENTRY32);
+BOOL WINAPI Module32FirstW(HANDLE,LPMODULEENTRY32W);
+BOOL WINAPI Module32Next(HANDLE,LPMODULEENTRY32);
+BOOL WINAPI Module32NextW(HANDLE,LPMODULEENTRY32W);
+BOOL WINAPI Process32First(HANDLE,LPPROCESSENTRY32);
+BOOL WINAPI Process32FirstW(HANDLE,LPPROCESSENTRY32W);
+BOOL WINAPI Process32Next(HANDLE,LPPROCESSENTRY32);
+BOOL WINAPI Process32NextW(HANDLE,LPPROCESSENTRY32W);
+BOOL WINAPI Thread32First(HANDLE,LPTHREADENTRY32);
+BOOL WINAPI Thread32Next(HANDLE,LPTHREADENTRY32);
+BOOL WINAPI Toolhelp32ReadProcessMemory(DWORD,LPCVOID,LPVOID,DWORD,LPDWORD);
+HANDLE WINAPI CreateToolhelp32Snapshot(DWORD,DWORD);
+
+#ifdef UNICODE
+#define LPMODULEENTRY32 LPMODULEENTRY32W
+#define LPPROCESSENTRY32 LPPROCESSENTRY32W
+#define MODULEENTRY32 MODULEENTRY32W
+#define Module32First Module32FirstW
+#define Module32Next Module32NextW
+#define PMODULEENTRY32 PMODULEENTRY32W
+#define PPROCESSENTRY32 PPROCESSENTRY32W
+#define PROCESSENTRY32 PROCESSENTRY32W
+#define Process32First Process32FirstW
+#define Process32Next Process32NextW
+#endif // UNICODE
+ */
+#endif /* 0 */
+
+/* EOF */
--- /dev/null
+/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+#include <msvcrt/ctype.h>
+
+unsigned short _ctype[] = {
+ 0, /* <EOF>, 0xFFFF */
+ _CONTROL, /* CTRL+@, 0x00 */
+ _CONTROL, /* CTRL+A, 0x01 */
+ _CONTROL, /* CTRL+B, 0x02 */
+ _CONTROL, /* CTRL+C, 0x03 */
+ _CONTROL, /* CTRL+D, 0x04 */
+ _CONTROL, /* CTRL+E, 0x05 */
+ _CONTROL, /* CTRL+F, 0x06 */
+ _CONTROL, /* CTRL+G, 0x07 */
+ _CONTROL, /* CTRL+H, 0x08 */
+ _CONTROL | _SPACE, /* CTRL+I, 0x09 */
+ _CONTROL | _SPACE, /* CTRL+J, 0x0a */
+ _CONTROL | _SPACE, /* CTRL+K, 0x0b */
+ _CONTROL | _SPACE, /* CTRL+L, 0x0c */
+ _CONTROL | _SPACE, /* CTRL+M, 0x0d */
+ _CONTROL, /* CTRL+N, 0x0e */
+ _CONTROL, /* CTRL+O, 0x0f */
+ _CONTROL, /* CTRL+P, 0x10 */
+ _CONTROL, /* CTRL+Q, 0x11 */
+ _CONTROL, /* CTRL+R, 0x12 */
+ _CONTROL, /* CTRL+S, 0x13 */
+ _CONTROL, /* CTRL+T, 0x14 */
+ _CONTROL, /* CTRL+U, 0x15 */
+ _CONTROL, /* CTRL+V, 0x16 */
+ _CONTROL, /* CTRL+W, 0x17 */
+ _CONTROL, /* CTRL+X, 0x18 */
+ _CONTROL, /* CTRL+Y, 0x19 */
+ _CONTROL, /* CTRL+Z, 0x1a */
+ _CONTROL, /* CTRL+[, 0x1b */
+ _CONTROL, /* CTRL+\, 0x1c */
+ _CONTROL, /* CTRL+], 0x1d */
+ _CONTROL, /* CTRL+^, 0x1e */
+ _CONTROL, /* CTRL+_, 0x1f */
+ _SPACE | _BLANK, /* ` ', 0x20 */
+ _PUNCT, /* `!', 0x21 */
+ _PUNCT, /* 0x22 */
+ _PUNCT, /* `#', 0x23 */
+ _PUNCT, /* `$', 0x24 */
+ _PUNCT, /* `%', 0x25 */
+ _PUNCT, /* `&', 0x26 */
+ _PUNCT, /* 0x27 */
+ _PUNCT, /* `(', 0x28 */
+ _PUNCT, /* `)', 0x29 */
+ _PUNCT, /* `*', 0x2a */
+ _PUNCT, /* `+', 0x2b */
+ _PUNCT, /* `,', 0x2c */
+ _PUNCT, /* `-', 0x2d */
+ _PUNCT, /* `.', 0x2e */
+ _PUNCT, /* `/', 0x2f */
+ _DIGIT | _HEX, /* `0', 0x30 */
+ _DIGIT | _HEX, /* `1', 0x31 */
+ _DIGIT | _HEX, /* `2', 0x32 */
+ _DIGIT | _HEX, /* `3', 0x33 */
+ _DIGIT | _HEX, /* `4', 0x34 */
+ _DIGIT | _HEX, /* `5', 0x35 */
+ _DIGIT | _HEX, /* `6', 0x36 */
+ _DIGIT | _HEX, /* `7', 0x37 */
+ _DIGIT | _HEX, /* `8', 0x38 */
+ _DIGIT | _HEX, /* `9', 0x39 */
+ _PUNCT, /* `:', 0x3a */
+ _PUNCT, /* `;', 0x3b */
+ _PUNCT, /* `<', 0x3c */
+ _PUNCT, /* `=', 0x3d */
+ _PUNCT, /* `>', 0x3e */
+ _PUNCT, /* `?', 0x3f */
+ _PUNCT, /* `@', 0x40 */
+ _UPPER | _HEX, /* `A', 0x41 */
+ _UPPER | _HEX, /* `B', 0x42 */
+ _UPPER | _HEX, /* `C', 0x43 */
+ _UPPER | _HEX, /* `D', 0x44 */
+ _UPPER | _HEX, /* `E', 0x45 */
+ _UPPER | _HEX, /* `F', 0x46 */
+ _UPPER, /* `G', 0x47 */
+ _UPPER, /* `H', 0x48 */
+ _UPPER, /* `I', 0x49 */
+ _UPPER, /* `J', 0x4a */
+ _UPPER, /* `K', 0x4b */
+ _UPPER, /* `L', 0x4c */
+ _UPPER, /* `M', 0x4d */
+ _UPPER, /* `N', 0x4e */
+ _UPPER, /* `O', 0x4f */
+ _UPPER, /* `P', 0x50 */
+ _UPPER, /* `Q', 0x51 */
+ _UPPER, /* `R', 0x52 */
+ _UPPER, /* `S', 0x53 */
+ _UPPER, /* `T', 0x54 */
+ _UPPER, /* `U', 0x55 */
+ _UPPER, /* `V', 0x56 */
+ _UPPER, /* `W', 0x57 */
+ _UPPER, /* `X', 0x58 */
+ _UPPER, /* `Y', 0x59 */
+ _UPPER, /* `Z', 0x5a */
+ _PUNCT, /* `[', 0x5b */
+ _PUNCT, /* 0x5c */
+ _PUNCT, /* `]', 0x5d */
+ _PUNCT, /* `^', 0x5e */
+ _PUNCT, /* `_', 0x5f */
+ _PUNCT, /* 0x60 */
+ _LOWER | _HEX, /* `a', 0x61 */
+ _LOWER | _HEX, /* `b', 0x62 */
+ _LOWER | _HEX, /* `c', 0x63 */
+ _LOWER | _HEX, /* `d', 0x64 */
+ _LOWER | _HEX, /* `e', 0x65 */
+ _LOWER | _HEX, /* `f', 0x66 */
+ _LOWER, /* `g', 0x67 */
+ _LOWER, /* `h', 0x68 */
+ _LOWER, /* `i', 0x69 */
+ _LOWER, /* `j', 0x6a */
+ _LOWER, /* `k', 0x6b */
+ _LOWER, /* `l', 0x6c */
+ _LOWER, /* `m', 0x6d */
+ _LOWER, /* `n', 0x6e */
+ _LOWER, /* `o', 0x6f */
+ _LOWER, /* `p', 0x70 */
+ _LOWER, /* `q', 0x71 */
+ _LOWER, /* `r', 0x72 */
+ _LOWER, /* `s', 0x73 */
+ _LOWER, /* `t', 0x74 */
+ _LOWER, /* `u', 0x75 */
+ _LOWER, /* `v', 0x76 */
+ _LOWER, /* `w', 0x77 */
+ _LOWER, /* `x', 0x78 */
+ _LOWER, /* `y', 0x79 */
+ _LOWER, /* `z', 0x7a */
+ _PUNCT, /* `{', 0x7b */
+ _PUNCT, /* `|', 0x7c */
+ _PUNCT, /* `}', 0x7d */
+ _PUNCT, /* `~', 0x7e */
+ _CONTROL, /* 0x7f */
+ 0, /* 0x80 */
+ 0, /* 0x81 */
+ 0, /* 0x82 */
+ 0, /* 0x83 */
+ 0, /* 0x84 */
+ 0, /* 0x85 */
+ 0, /* 0x86 */
+ 0, /* 0x87 */
+ 0, /* 0x88 */
+ 0, /* 0x89 */
+ 0, /* 0x8a */
+ 0, /* 0x8b */
+ 0, /* 0x8c */
+ 0, /* 0x8d */
+ 0, /* 0x8e */
+ 0, /* 0x8f */
+ 0, /* 0x90 */
+ 0, /* 0x91 */
+ 0, /* 0x92 */
+ 0, /* 0x93 */
+ 0, /* 0x94 */
+ 0, /* 0x95 */
+ 0, /* 0x96 */
+ 0, /* 0x97 */
+ 0, /* 0x98 */
+ 0, /* 0x99 */
+ 0, /* 0x9a */
+ 0, /* 0x9b */
+ 0, /* 0x9c */
+ 0, /* 0x9d */
+ 0, /* 0x9e */
+ 0, /* 0x9f */
+ 0, /* 0xa0 */
+ 0, /* 0xa1 */
+ 0, /* 0xa2 */
+ 0, /* 0xa3 */
+ 0, /* 0xa4 */
+ 0, /* 0xa5 */
+ 0, /* 0xa6 */
+ 0, /* 0xa7 */
+ 0, /* 0xa8 */
+ 0, /* 0xa9 */
+ 0, /* 0xaa */
+ 0, /* 0xab */
+ 0, /* 0xac */
+ 0, /* 0xad */
+ 0, /* 0xae */
+ 0, /* 0xaf */
+ 0, /* 0xb0 */
+ 0, /* 0xb1 */
+ 0, /* 0xb2 */
+ 0, /* 0xb3 */
+ 0, /* 0xb4 */
+ 0, /* 0xb5 */
+ 0, /* 0xb6 */
+ 0, /* 0xb7 */
+ 0, /* 0xb8 */
+ 0, /* 0xb9 */
+ 0, /* 0xba */
+ 0, /* 0xbb */
+ 0, /* 0xbc */
+ 0, /* 0xbd */
+ 0, /* 0xbe */
+ 0, /* 0xbf */
+ 0, /* 0xc0 */
+ 0, /* 0xc1 */
+ 0, /* 0xc2 */
+ 0, /* 0xc3 */
+ 0, /* 0xc4 */
+ 0, /* 0xc5 */
+ 0, /* 0xc6 */
+ 0, /* 0xc7 */
+ 0, /* 0xc8 */
+ 0, /* 0xc9 */
+ 0, /* 0xca */
+ 0, /* 0xcb */
+ 0, /* 0xcc */
+ 0, /* 0xcd */
+ 0, /* 0xce */
+ 0, /* 0xcf */
+ 0, /* 0xd0 */
+ 0, /* 0xd1 */
+ 0, /* 0xd2 */
+ 0, /* 0xd3 */
+ 0, /* 0xd4 */
+ 0, /* 0xd5 */
+ 0, /* 0xd6 */
+ 0, /* 0xd7 */
+ 0, /* 0xd8 */
+ 0, /* 0xd9 */
+ 0, /* 0xda */
+ 0, /* 0xdb */
+ 0, /* 0xdc */
+ 0, /* 0xdd */
+ 0, /* 0xde */
+ 0, /* 0xdf */
+ 0, /* 0xe0 */
+ 0, /* 0xe1 */
+ 0, /* 0xe2 */
+ 0, /* 0xe3 */
+ 0, /* 0xe4 */
+ 0, /* 0xe5 */
+ 0, /* 0xe6 */
+ 0, /* 0xe7 */
+ 0, /* 0xe8 */
+ 0, /* 0xe9 */
+ 0, /* 0xea */
+ 0, /* 0xeb */
+ 0, /* 0xec */
+ 0, /* 0xed */
+ 0, /* 0xee */
+ 0, /* 0xef */
+ 0, /* 0xf0 */
+ 0, /* 0xf1 */
+ 0, /* 0xf2 */
+ 0, /* 0xf3 */
+ 0, /* 0xf4 */
+ 0, /* 0xf5 */
+ 0, /* 0xf6 */
+ 0, /* 0xf7 */
+ 0, /* 0xf8 */
+ 0, /* 0xf9 */
+ 0, /* 0xfa */
+ 0, /* 0xfb */
+ 0, /* 0xfc */
+ 0, /* 0xfd */
+ 0, /* 0xfe */
+ 0 /* 0xff */
+};
+
+/* EOF */
--- /dev/null
+#include <windows.h>
+#include <msvcrt/ctype.h>
+#include <msvcrt/direct.h>
+
+
+int _wchdir (const wchar_t *_path)
+{
+ if (_path[1] == L':')
+ _chdrive(towlower(_path[0] - L'a')+1);
+ if (!SetCurrentDirectoryW((wchar_t *)_path))
+ return -1;
+ return 0;
+}
--- /dev/null
+#include <windows.h>
+#include <msvcrt/direct.h>
+#include <msvcrt/stdlib.h>
+
+
+wchar_t* _wgetcwd(wchar_t* buffer, int maxlen)
+{
+ wchar_t *cwd;
+ int len;
+ if (buffer == NULL) {
+ cwd = malloc(MAX_PATH * sizeof(wchar_t));
+ len = MAX_PATH;
+ } else {
+ cwd = buffer;
+ len = maxlen;
+ }
+ if (GetCurrentDirectoryW(len, cwd) == 0 )
+ return NULL;
+ return cwd;
+}
--- /dev/null
+#include <windows.h>
+#include <msvcrt/direct.h>
+
+
+wchar_t* _wgetdcwd(int nDrive, wchar_t* caBuffer, int nBufLen)
+{
+ int i =0;
+ int dr = _getdrive();
+
+ if (nDrive < 1 || nDrive > 26)
+ return NULL;
+
+ if (dr != nDrive)
+ _chdrive(nDrive);
+
+ i = GetCurrentDirectoryW(nBufLen, caBuffer);
+ if (i == nBufLen)
+ return NULL;
+
+ if (dr != nDrive)
+ _chdrive(dr);
+
+ return caBuffer;
+}
--- /dev/null
+#include <windows.h>
+#include <msvcrt/direct.h>
+
+
+int _wmkdir(const wchar_t* _path)
+{
+ if (!CreateDirectoryW(_path, NULL))
+ return -1;
+ return 0;
+}
--- /dev/null
+#include <windows.h>
+#include <msvcrt/direct.h>
+
+int _wrmdir(const wchar_t* _path)
+{
+ if (!RemoveDirectoryW(_path))
+ return -1;
+ return 0;
+}
--- /dev/null
+#include <windows.h>
+#include <msvcrt/io.h>
+
+
+__int64 _filelengthi64(int _fd)
+{
+ long lo_length, hi_length;
+
+ lo_length = GetFileSize(_get_osfhandle(_fd), &hi_length);
+ return((((__int64)hi_length) << 32) + lo_length);
+}
--- /dev/null
+#include <windows.h>
+#include <msvcrt/io.h>
+#include <msvcrt/internal/file.h>
+
+
+//#define SETFILEPOINTEREX_AVAILABLE
+
+__int64 _lseeki64(int _fildes, __int64 _offset, int _whence)
+{
+#ifdef SETFILEPOINTEREX_AVAILABLE
+ LARGE_INTEGER new_pos;
+ LARGE_INTEGER offset;
+ offset.QuadPart = _offset;
+
+// if (invalid_filehnd(_fildes)) {
+// errno = EBADF;
+// return -1L;
+// }
+ if (SetFilePointerEx((HANDLE)filehnd(_fildes), offset, &new_pos, _whence)) {
+ } else {
+ //errno = EINVAL;
+ return -1L;
+ }
+ return new_pos.QuadPart;
+#else
+ //ULONG lo_pos;
+ //DWORD hi_pos = 0; // must equal 0 or -1 if supplied, -1 for negative 32 seek value
+ //lo_pos = SetFilePointer((HANDLE)filehnd(_fildes), _offset, &hi_pos, _whence);
+ //return((((__int64)hi_pos) << 32) + lo_pos);
+
+ LARGE_INTEGER offset;
+ offset.QuadPart = _offset;
+
+ offset.u.LowPart = SetFilePointer((HANDLE)filehnd(_fildes),
+ offset.u.LowPart, &offset.u.HighPart, _whence);
+ return ((((__int64)offset.u.HighPart) << 32) + offset.u.LowPart);
+
+#endif /*SETFILEPOINTEREX_AVAILABLE*/
+}
--- /dev/null
+#include <msvcrt/errno.h>
+#include <msvcrt/io.h>
+
+
+__int64 _telli64(int _file)
+{
+ return _lseeki64(_file, 0, SEEK_CUR);
+}
--- /dev/null
+#include <windows.h>
+#include <msvcrt/io.h>
+#include <msvcrt/errno.h>
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+
+int _waccess(const wchar_t *_path, int _amode)
+{
+ DWORD Attributes = GetFileAttributesW(_path);
+
+ if (Attributes == -1) {
+ __set_errno(ENOENT);
+ return -1;
+ }
+ if ((_amode & W_OK) == W_OK) {
+ if ((Attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY) {
+ __set_errno(EACCES);
+ return -1;
+ }
+ }
+ if ((_amode & D_OK) == D_OK) {
+ if ((Attributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY) {
+ __set_errno(EACCES);
+ return -1;
+ }
+ }
+ return 0;
+}
--- /dev/null
+#include <windows.h>
+#include <msvcrt/io.h>
+
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+#define mode_t int
+
+
+int _wchmod(const wchar_t* filename, mode_t mode)
+{
+ DWORD FileAttributes = 0;
+ DPRINT("_wchmod('%S', %x)\n", filename, mode);
+
+ FileAttributes = GetFileAttributesW(filename);
+ if ( FileAttributes == -1 )
+ return -1;
+
+ if ( mode == 0 )
+ return -1;
+
+ if ((mode & _S_IREAD) == _S_IREAD && (mode & _S_IWRITE) != _S_IWRITE)
+ FileAttributes &= FILE_ATTRIBUTE_READONLY;
+ else if (((mode & _S_IREAD) != _S_IREAD) && ((mode & _S_IWRITE) == _S_IWRITE))
+ FileAttributes &= FILE_ATTRIBUTE_NORMAL;
+ else
+ FileAttributes &= FILE_ATTRIBUTE_NORMAL;
+
+ if (SetFileAttributesW(filename, FileAttributes) == FALSE)
+ return -1;
+
+ return 1;
+}
--- /dev/null
+#include <msvcrt/io.h>
+#include <msvcrt/fcntl.h>
+
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+
+int _wcreat(const wchar_t* filename, int mode)
+{
+ DPRINT("_wcreat('%S', mode %x)\n", filename, mode);
+ return _wopen(filename,_O_CREAT|_O_TRUNC,mode);
+}
--- /dev/null
+#include <windows.h>
+#include <msvcrt/io.h>
+#include <msvcrt/string.h>
+#include <msvcrt/internal/file.h>
+
+
+int _wfindfirst(const wchar_t* _name, struct _wfinddata_t* result)
+{
+ WIN32_FIND_DATAW FindFileData;
+ wchar_t dir[MAX_PATH];
+ long hFindFile;
+ int len = 0;
+
+ if ( _name == NULL || _name[0] == 0 ) {
+ len = GetCurrentDirectoryW(MAX_PATH-4, dir);
+ if (dir[len-1] != L'\\') {
+ dir[len] = L'\\';
+ dir[len+1] = 0;
+ }
+ wcscat(dir, L"*.*");
+ } else {
+ wcscpy(dir, _name);
+ }
+
+ hFindFile = (long)FindFirstFileW(dir, &FindFileData);
+ if (hFindFile == -1) {
+ memset(result,0,sizeof(struct _wfinddata_t));
+ return -1;
+ }
+
+ result->attrib = FindFileData.dwFileAttributes;
+ result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL);
+ result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL);
+ result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL);
+ result->size = FindFileData.nFileSizeLow;
+ wcsncpy(result->name,FindFileData.cFileName,MAX_PATH);
+
+ // if no wildcard the find file handle can be closed right away
+ // a return value of 0 can flag this.
+ if (!wcschr(dir, L'*') && !wcschr(dir, L'?')) {
+ _findclose(hFindFile);
+ return 0;
+ }
+
+ return hFindFile;
+}
+
+int _findfirsti64(const char *_name, struct _finddatai64_t *result)
+{
+ WIN32_FIND_DATAA FindFileData;
+ char dir[MAX_PATH];
+ long hFindFile;
+ int len = 0;
+
+ if ( _name == NULL || _name[0] == 0 )
+ {
+ len = GetCurrentDirectoryA(MAX_PATH-4,dir);
+ if (dir[len-1] != '\\')
+ {
+ dir[len] = '\\';
+ dir[len+1] = 0;
+ }
+ strcat(dir, "*.*");
+ }
+ else
+ strcpy(dir, _name);
+
+ hFindFile = (long)FindFirstFileA(dir, &FindFileData);
+ if (hFindFile == -1)
+ {
+ memset(result,0,sizeof(struct _finddatai64_t));
+ return -1;
+ }
+
+ result->attrib = FindFileData.dwFileAttributes;
+ result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL);
+ result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL);
+ result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL);
+ result->size =
+ (((__int64)FindFileData.nFileSizeLow)<<32) + FindFileData.nFileSizeLow;
+ strncpy(result->name,FindFileData.cFileName,MAX_PATH);
+
+ // if no wildcard the find file handle can be closed right away
+ // a return value of 0 can flag this.
+
+ if (!strchr(dir,'*') && !strchr(dir,'?')) {
+ _findclose(hFindFile);
+ return 0;
+ }
+ return hFindFile;
+}
+
+int _findnexti64(int handle, struct _finddatai64_t *result)
+{
+ WIN32_FIND_DATAA FindFileData;
+
+ // check no wildcards or invalid handle
+ if (handle == 0 || handle == -1)
+ return 0;
+
+ if (!FindNextFileA((void *)handle, &FindFileData))
+ return -1;
+
+ result->attrib = FindFileData.dwFileAttributes;
+ result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL);
+ result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL);
+ result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL);
+ result->size =
+ (((__int64)FindFileData.nFileSizeLow)<<32) + FindFileData.nFileSizeLow;
+ strncpy(result->name,FindFileData.cFileName,MAX_PATH);
+
+ return 0;
+}
+
+int _wfindfirsti64(const wchar_t *_name, struct _wfinddatai64_t *result)
+{
+ WIN32_FIND_DATAW FindFileData;
+ wchar_t dir[MAX_PATH];
+ long hFindFile;
+ int len = 0;
+
+ if (_name == NULL || _name[0] == 0)
+ {
+ len = GetCurrentDirectoryW(MAX_PATH-4,dir);
+ if (dir[len-1] != L'\\')
+ {
+ dir[len] = L'\\';
+ dir[len+1] = 0;
+ }
+ wcscat(dir, L"*.*");
+ }
+ else
+ wcscpy(dir, _name);
+
+ hFindFile = (long)FindFirstFileW(dir, &FindFileData);
+ if (hFindFile == -1)
+ {
+ memset(result,0,sizeof(struct _wfinddatai64_t));
+ return -1;
+ }
+
+ result->attrib = FindFileData.dwFileAttributes;
+ result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL);
+ result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL);
+ result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL);
+ result->size =
+ (((__int64)FindFileData.nFileSizeLow)<<32) + FindFileData.nFileSizeLow;
+ wcsncpy(result->name,FindFileData.cFileName,MAX_PATH);
+
+ // if no wildcard the find file handle can be closed right away
+ // a return value of 0 can flag this.
+
+ if (!wcschr(dir,L'*') && !wcschr(dir,L'?'))
+ {
+ _findclose(hFindFile);
+ return 0;
+ }
+
+ return hFindFile;
+}
+
+int _wfindnext(int handle, struct _wfinddata_t *result)
+{
+ WIN32_FIND_DATAW FindFileData;
+
+ // check no wildcards or invalid handle
+ if (handle == 0 || handle == -1)
+ return 0;
+
+ if (!FindNextFileW((void *)handle, &FindFileData))
+ return -1;
+
+ result->attrib = FindFileData.dwFileAttributes;
+ result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL);
+ result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL);
+ result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL);
+ result->size = FindFileData.nFileSizeLow;
+ wcsncpy(result->name,FindFileData.cFileName, MAX_PATH);
+
+ return 0;
+}
+
+int _wfindnexti64(int handle, struct _wfinddatai64_t *result)
+{
+ WIN32_FIND_DATAW FindFileData;
+
+ // check no wildcards or invalid handle
+ if (handle == 0 || handle == -1)
+ return 0;
+
+ if (!FindNextFileW((void *)handle, &FindFileData))
+ return -1;
+
+ result->attrib = FindFileData.dwFileAttributes;
+ result->time_create = FileTimeToUnixTime(&FindFileData.ftCreationTime,NULL);
+ result->time_access = FileTimeToUnixTime(&FindFileData.ftLastAccessTime,NULL);
+ result->time_write = FileTimeToUnixTime(&FindFileData.ftLastWriteTime,NULL);
+ result->size =
+ (((__int64)FindFileData.nFileSizeLow)<<32) + FindFileData.nFileSizeLow;
+ wcsncpy(result->name,FindFileData.cFileName,MAX_PATH);
+
+ return 0;
+}
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details
+ * PROJECT: ReactOS system libraries
+ * FILE: lib/msvcrt/io/mktemp.c
+ * PURPOSE: Makes a temp file based on a template
+ * PROGRAMER: DJ Delorie
+ Boudewijn Dekker
+ * UPDATE HISTORY:
+ * 28/12/98: Appropriated for the Reactos Kernel
+ */
+
+/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
+/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+
+#include <msvcrt/stdio.h>
+#include <msvcrt/string.h>
+#include <msvcrt/io.h>
+
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+
+wchar_t* _wmktemp (wchar_t *_template)
+{
+ static int count = 0;
+ wchar_t *cp, *dp;
+ int i, len, xcount, loopcnt;
+
+ DPRINT("_wmktemp('%S')\n", _template);
+ len = wcslen (_template);
+ cp = _template + len;
+
+ xcount = 0;
+ while (xcount < 6 && cp > _template && cp[-1] == L'X')
+ xcount++, cp--;
+
+ if (xcount) {
+ dp = cp;
+ while (dp > _template && dp[-1] != L'/' && dp[-1] != L'\\' && dp[-1] != L':')
+ dp--;
+
+ /* Keep the first characters of the template, but turn the rest into
+ Xs. */
+ while (cp > dp + 8 - xcount) {
+ *--cp = L'X';
+ xcount = (xcount >= 6) ? 6 : 1 + xcount;
+ }
+
+ /* If dots occur too early -- squash them. */
+ while (dp < cp) {
+ if (*dp == L'.') *dp = L'a';
+ dp++;
+ }
+
+ /* Try to add ".tmp" to the filename. Truncate unused Xs. */
+ if (cp + xcount + 3 < _template + len)
+ wcscpy (cp + xcount, L".tmp");
+ else
+ cp[xcount] = 0;
+
+ /* This loop can run up to 2<<(5*6) times, or about 10^9 times. */
+ for (loopcnt = 0; loopcnt < (1 << (5 * xcount)); loopcnt++) {
+ int c = count++;
+ for (i = 0; i < xcount; i++, c >>= 5)
+ cp[i] = L"abcdefghijklmnopqrstuvwxyz012345"[c & 0x1f];
+ if (_waccess(_template,0) == -1)
+ return _template;
+ }
+ }
+
+ /* Failure: truncate the template and return NULL. */
+ *_template = 0;
+ return 0;
+}
--- /dev/null
+/* $Id$
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS system libraries
+ * FILE: lib/msvcrt/io/open.c
+ * PURPOSE: Opens a file and translates handles to fileno
+ * PROGRAMER: Boudewijn Dekker
+ * UPDATE HISTORY:
+ * 28/12/98: Created
+ */
+
+// rember to interlock the allocation of fileno when making this thread safe
+// possibly store extra information at the handle
+
+#include <windows.h>
+#if !defined(NDEBUG) && defined(DBG)
+#include <msvcrt/stdarg.h>
+#endif
+#include <msvcrt/io.h>
+#include <msvcrt/fcntl.h>
+#include <msvcrt/sys/stat.h>
+#include <msvcrt/stdlib.h>
+#include <msvcrt/internal/file.h>
+#include <msvcrt/string.h>
+#include <msvcrt/share.h>
+#include <msvcrt/errno.h>
+
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+
+int _wopen(const wchar_t* _path, int _oflag, ...)
+{
+#if !defined(NDEBUG) && defined(DBG)
+ va_list arg;
+ int pmode;
+#endif
+ HANDLE hFile;
+ DWORD dwDesiredAccess = 0;
+ DWORD dwShareMode = 0;
+ DWORD dwCreationDistribution = 0;
+ DWORD dwFlagsAndAttributes = 0;
+ SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
+
+#if !defined(NDEBUG) && defined(DBG)
+ va_start(arg, _oflag);
+ pmode = va_arg(arg, int);
+#endif
+
+// DPRINT("_wopen('%S', %x, (%x))\n", _path, _oflag, pmode);
+
+ if ((_oflag & S_IREAD) == S_IREAD)
+ dwShareMode = FILE_SHARE_READ;
+ else if ( ( _oflag & S_IWRITE) == S_IWRITE) {
+ dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ }
+
+ /*
+ *
+ * _O_BINARY Opens file in binary (untranslated) mode. (See fopen for a description of binary mode.)
+ * _O_TEXT Opens file in text (translated) mode. (For more information, see Text and Binary Mode File I/O and fopen.)
+ *
+ * _O_APPEND Moves file pointer to end of file before every write operation.
+ */
+#if 0
+ if ((_oflag & _O_RDWR) == _O_RDWR)
+ dwDesiredAccess |= GENERIC_WRITE|GENERIC_READ | FILE_READ_DATA |
+ FILE_WRITE_DATA | FILE_READ_ATTRIBUTES |
+ FILE_WRITE_ATTRIBUTES;
+ else if ((_oflag & O_RDONLY) == O_RDONLY)
+ dwDesiredAccess |= GENERIC_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES |
+ FILE_WRITE_ATTRIBUTES;
+ else if ((_oflag & _O_WRONLY) == _O_WRONLY)
+ dwDesiredAccess |= GENERIC_WRITE | FILE_WRITE_DATA |
+ FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES;
+#else
+ if ((_oflag & _O_WRONLY) == _O_WRONLY)
+ dwDesiredAccess |= GENERIC_WRITE | FILE_WRITE_DATA |
+ FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES;
+ else if ((_oflag & _O_RDWR) == _O_RDWR)
+ dwDesiredAccess |= GENERIC_WRITE|GENERIC_READ | FILE_READ_DATA |
+ FILE_WRITE_DATA | FILE_READ_ATTRIBUTES |
+ FILE_WRITE_ATTRIBUTES;
+ else //if ((_oflag & O_RDONLY) == O_RDONLY)
+ dwDesiredAccess |= GENERIC_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES |
+ FILE_WRITE_ATTRIBUTES;
+#endif
+
+ if ((_oflag & S_IREAD) == S_IREAD)
+ dwShareMode |= FILE_SHARE_READ;
+
+ if ((_oflag & S_IWRITE) == S_IWRITE)
+ dwShareMode |= FILE_SHARE_WRITE;
+
+ if ((_oflag & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL))
+ dwCreationDistribution |= CREATE_NEW;
+
+ else if ((_oflag & O_TRUNC) == O_TRUNC) {
+ if ((_oflag & O_CREAT) == O_CREAT)
+ dwCreationDistribution |= CREATE_ALWAYS;
+ else if ((_oflag & O_RDONLY) != O_RDONLY)
+ dwCreationDistribution |= TRUNCATE_EXISTING;
+ }
+ else if ((_oflag & _O_APPEND) == _O_APPEND)
+ dwCreationDistribution |= OPEN_EXISTING;
+ else if ((_oflag & _O_CREAT) == _O_CREAT)
+ dwCreationDistribution |= OPEN_ALWAYS;
+ else
+ dwCreationDistribution |= OPEN_EXISTING;
+
+ if ((_oflag & _O_RANDOM) == _O_RANDOM)
+ dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
+ if ((_oflag & _O_SEQUENTIAL) == _O_SEQUENTIAL)
+ dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
+
+ if ((_oflag & _O_TEMPORARY) == _O_TEMPORARY)
+ dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
+
+ if ((_oflag & _O_SHORT_LIVED) == _O_SHORT_LIVED)
+ dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
+
+ if (_oflag & _O_NOINHERIT)
+ sa.bInheritHandle = FALSE;
+
+ hFile = CreateFileW(_path,
+ dwDesiredAccess,
+ dwShareMode,
+ &sa,
+ dwCreationDistribution,
+ dwFlagsAndAttributes,
+ NULL);
+ if (hFile == (HANDLE)-1)
+ return -1;
+ return __fileno_alloc(hFile,_oflag);
+}
+
+int _wsopen(wchar_t* path, int access, int shflag, int mode)
+{
+ return _wopen((path), (access)|(shflag), (mode));
+}
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS system libraries
+ * FILE: lib/msvcrt/io/unlink.c
+ * PURPOSE: Deletes a file
+ * PROGRAMER: Boudewijn Dekker
+ * UPDATE HISTORY:
+ * 28/12/98: Created
+ */
+#include <windows.h>
+#include <msvcrt/io.h>
+
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+
+int _wunlink(const wchar_t* filename)
+{
+ DPRINT("_wunlink('%S')\n", filename);
+ if (!DeleteFileW(filename))
+ return -1;
+ return 0;
+}
--- /dev/null
+#include <msvcrt/stdio.h>
+#include <msvcrt/io.h>
+#include <msvcrt/errno.h>
+#include <msvcrt/sys/utime.h>
+#include <msvcrt/internal/file.h>
+
+
+int _wutime(const wchar_t* filename, struct _utimbuf* buf)
+{
+ int fn;
+ int ret;
+
+ fn = _wopen(filename, _O_RDWR);
+ if (fn == -1) {
+ __set_errno(EBADF);
+ return -1;
+ }
+ ret = _futime(fn, buf);
+ if (_close(fn) < 0)
+ return -1;
+ return ret;
+}
--- /dev/null
+#include <msvcrt/math.h>
+
+#pragma function(fmod,sqrt)
+#pragma function(log,log10,pow,exp)
+#pragma function(tan,atan,atan2,tanh)
+#pragma function(cos,acos,cosh)
+#pragma function(sin,asin,sinh)
+
+
+double linkme_ceil(double __x)
+{
+ return ceil(__x);
+}
+
+double linkme_fabs(double __x)
+{
+ return fabs(__x);
+}
+
+double linkme_floor(double __x)
+{
+ return floor(__x);
+}
+
+double linkme_ldexp(double __x, int __y)
+{
+ return ldexp(__x, __y);
+}
+
+double linkme_log2(double __x)
+{
+ //return log2(__x);
+ return 0;
+}
+
+double linkme_fmod(double __x, double __y)
+{
+ return fmod(__x, __y);
+}
+
+double linkme_sqrt(double __x)
+{
+ return sqrt(__x);
+}
+
+double linkme_log(double __x)
+{
+ return log(__x);
+}
+
+double linkme_log10(double __x)
+{
+ return log10(__x);
+}
+
+double linkme_pow(double __x, double __y)
+{
+ return pow(__x, __y);
+}
+
+double linkme_exp(double __x)
+{
+ return exp(__x);
+}
+
+double linkme_tan(double __x)
+{
+ return tan(__x);
+}
+
+double linkme_atan(double __x)
+{
+ return atan(__x);
+}
+
+double linkme_atan2(double __x, double __y)
+{
+ return atan2(__x, __y);
+}
+
+double linkme_tanh(double __x)
+{
+ return tanh(__x);
+}
+
+double linkme_cos(double __x)
+{
+ return cos(__x);
+}
+
+double linkme_acos(double __x)
+{
+ return acos(__x);
+}
+
+double linkme_cosh(double __x)
+{
+ return cosh(__x);
+}
+
+double linkme_sin(double __x)
+{
+ return sin(__x);
+}
+
+double linkme_asin(double __x)
+{
+ return asin(__x);
+}
+
+double linkme_sinh(double __x)
+{
+ return sinh(__x);
+}
+/*
+linkme_log2
+linkme_floor
+_linkme_ldexp
+_linkme_pow
+ */
--- /dev/null
+/* $Id$
+ *
+ * ReactOS MSVCRT.DLL Compatibility Library
+ */
+#include <windows.h>
+//#include <msvcrt/stdlib.h>
+
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+#ifndef __GNUC__
+
+/* GLOBAL VARIABLES *******************************************************/
+
+int _fltused;
+
+
+/* FUNCTIONS **************************************************************/
+
+int
+STDCALL
+_except_handler3(void)
+{
+ return 0;
+}
+
+int
+STDCALL
+_local_unwind2(void)
+{
+ return 0;
+}
+
+int
+STDCALL
+_spawnlp(int a, const char* b, const char* args, ...)
+{
+ return 0;
+}
+
+#else /*__GNUC__*/
+
+int
+_spawnlp(int a, const char* b, const char* args, ...)
+{
+ return 0;
+}
+
+#endif /*__GNUC__*/
+
+
+/*
+int __cdecl _allmul(void)
+{
+ return 0;
+}
+
+int __cdecl _allshl(void)
+{
+ return 0;
+}
+
+void __cdecl _chkesp(int value1, int value2)
+{
+}
+
+int __cdecl _alloca_probe(void)
+{
+ return 0;
+}
+
+int STDCALL _abnormal_termination(void)
+{
+ return 0;
+}
+
+int STDCALL _setjmp(void)
+{
+ return 0;
+}
+*/
+/*
+BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved);
+
+int STDCALL _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
+{
+ BOOL result;
+
+ //__fileno_init();
+ //result = DllMain(hInst, ul_reason_for_call, lpReserved);
+
+ result = DllMain(hInst, DLL_PROCESS_ATTACH, lpReserved);
+
+
+ return (result ? 1 : 0);
+}
+ */
+
+/* EOF */
--- /dev/null
+/* $Id$
+ *
+ * dllmain.c
+ *
+ * ReactOS MSVCRT.DLL Compatibility Library
+ */
+
+#include <windows.h>
+#include <msvcrt/internal/tls.h>
+#include <msvcrt/stdlib.h>
+
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+
+unsigned int _osver = 0;
+unsigned int _winminor = 0;
+unsigned int _winmajor = 0;
+unsigned int _winver = 0;
+
+char *_acmdln = NULL; /* pointer to ascii command line */
+#undef _environ
+char **_environ = NULL; /* pointer to environment block */
+char ***_environ_dll = &_environ;/* pointer to environment block */
+char **__initenv = NULL;
+char *_pgmptr = NULL; /* pointer to program name */
+int __app_type = 0; //_UNKNOWN_APP; /* application type */
+int __mb_cur_max = 1;
+
+int _commode = _IOCOMMIT;
+
+
+int *__p__commode(void) // not exported by NTDLL
+{
+ return &_commode;
+}
+
+int BlockEnvToEnviron(void)
+{
+ char * ptr, * ptr2;
+ int i, len;
+
+ DPRINT("BlockEnvToEnviron()\n");
+
+ if (_environ) {
+ FreeEnvironmentStringsA(_environ[0]);
+ free(_environ);
+ _environ = NULL;
+ }
+ ptr2 = ptr = (char*)GetEnvironmentStringsA();
+ if (ptr == NULL) {
+ DPRINT("GetEnvironmentStringsA() returnd NULL\n");
+ return -1;
+ }
+ len = 0;
+ while (*ptr2) {
+ len++;
+ while (*ptr2++);
+ }
+ _environ = malloc((len + 1) * sizeof(char*));
+ if (_environ == NULL) {
+ FreeEnvironmentStringsA(ptr);
+ return -1;
+ }
+ for (i = 0; i < len && *ptr; i++) {
+ _environ[i] = ptr;
+ while (*ptr++);
+ }
+ _environ[i] = NULL;
+ return 0;
+}
+
+void __set_app_type(int app_type)
+{
+ __app_type = app_type;
+}
+
+char **__p__acmdln(void)
+{
+ return &_acmdln;
+}
+
+char ***__p__environ(void)
+{
+ return _environ_dll;
+}
+
+char ***__p___initenv(void)
+{
+ return &__initenv;
+}
+
+int *__p___mb_cur_max(void)
+{
+ return &__mb_cur_max;
+}
+
+unsigned int *__p__osver(void)
+{
+ return &_osver;
+}
+
+char **__p__pgmptr(void)
+{
+ return &_pgmptr;
+}
+
+unsigned int *__p__winmajor(void)
+{
+ return &_winmajor;
+}
+
+unsigned int *__p__winminor(void)
+{
+ return &_winminor;
+}
+
+unsigned int *__p__winver(void)
+{
+ return &_winver;
+}
+
+/* EOF */
--- /dev/null
+/* $Id$
+ *
+ */
+#include <windows.h>
+#include <msvcrt/errno.h>
+#include <msvcrt/process.h>
+
+
+unsigned long _beginthreadex(
+ void* security,
+ unsigned stack_size,
+ unsigned (__stdcall *start_address)(void*),
+ void* arglist,
+ unsigned initflag,
+ unsigned* thrdaddr)
+{
+ errno = ENOSYS;
+ return (unsigned long)-1;
+}
+
+
+void _endthreadex(unsigned retval)
+{
+}
+
+/* EOF */
--- /dev/null
+/* $Id$
+ *
+ * ReactOS msvcrt library
+ *
+ * fgets.c
+ *
+ * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
+ *
+ * Based on original work Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details
+ * 28/12/1998: Appropriated for Reactos
+ *
+ * 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
+ */
+/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
+
+#include <msvcrt/stdio.h>
+#include <msvcrt/internal/file.h>
+
+
+//#include <msvcrt/ctype.h>
+#ifndef WEOF
+#define WEOF (wchar_t)(0xFFFF)
+#endif
+
+wchar_t* fgetws(wchar_t* s, int n, FILE* f)
+{
+ wchar_t c = 0;
+ wchar_t* cs;
+
+ cs = s;
+ //while (--n > 0 && (c = getwc(f)) != WEOF) {
+ while (n > 0) {
+ c = getwc(f);
+ if (c == WEOF)
+ break;
+ n--;
+ *cs++ = c;
+ if (c == L'\n')
+ break;
+ }
+ if (c == WEOF && cs == s) {
+ return NULL;
+ }
+ *cs++ = L'\0';
+ return s;
+}
--- /dev/null
+#include <msvcrt/stdio.h>
+#include <msvcrt/internal/file.h>
+
+FILE* __alloc_file(void);
+
+
+FILE* _wfdopen(int handle, wchar_t* mode)
+{
+ FILE* file;
+ int rw;
+
+ if (handle == 0)
+ return stdin;
+
+ if (handle == 1)
+ return stdout;
+
+ if (handle == 2)
+ return stderr;
+
+ if (handle == 3)
+ return stdaux;
+
+ if (handle == 4)
+ return stdprn;
+
+ file = __alloc_file();
+ if (file == NULL)
+ return NULL;
+ file->_file = handle;
+
+ rw = (mode[1] == L'+') || (mode[1] && (mode[2] == L'+'));
+
+ if (*mode == L'a')
+ _lseek(handle, 0, SEEK_END);
+
+ file->_cnt = 0;
+ file->_file = handle;
+ file->_bufsiz = 0;
+
+// The mode of the stream must be compatible with the mode of the file descriptor.
+// this should be checked.
+
+ if (rw)
+ file->_flag = _IOREAD | _IOWRT;
+ else if (*mode == L'r')
+ file->_flag = _IOREAD;
+ else
+ file->_flag = _IOWRT;
+
+ file->_base = file->_ptr = NULL;
+
+ return file;
+}
--- /dev/null
+#include <windows.h>
+#include <msvcrt/stdio.h>
+#include <msvcrt/io.h>
+
+
+int _wrename(const wchar_t* old_, const wchar_t* new_)
+{
+ if (old_ == NULL || new_ == NULL)
+ return -1;
+
+ if (!MoveFileW(old_, new_))
+ return -1;
+
+ return 0;
+}
--- /dev/null
+#include <windows.h>
+#include <msvcrt/stdio.h>
+#include <msvcrt/stdlib.h>
+
+
+wchar_t* _wtempnam(const wchar_t* dir, const wchar_t* prefix)
+{
+ wchar_t* TempFileName = malloc(MAX_PATH);
+ wchar_t* d;
+
+ if (dir == NULL)
+ d = _wgetenv(L"TMP");
+ else
+ d = (wchar_t*)dir;
+
+ if (GetTempFileNameW(d, prefix, 1, TempFileName) == 0) {
+ free(TempFileName);
+ return NULL;
+ }
+
+ return TempFileName;
+}
--- /dev/null
+#include <windows.h>
+#include <msvcrt/stdio.h>
+#include <msvcrt/string.h>
+
+
+wchar_t* _wtmpnam(wchar_t* s)
+{
+ wchar_t PathName[MAX_PATH];
+ static wchar_t static_buf[MAX_PATH];
+
+ GetTempPathW(MAX_PATH, PathName);
+ GetTempFileNameW(PathName, L"ARI", 007, static_buf);
+ wcscpy(s, static_buf);
+
+ return s;
+}
--- /dev/null
+#include <windows.h>
+#include <msvcrt/stdlib.h>
+#include <msvcrt/ctype.h>
+
+
+#if 1
+
+int mbtowc(wchar_t *dst, const char *str, size_t n)
+{
+// printf("\t\t\tmbtowc(%p, %p, %d) called.\n", dst, str, n);
+
+ if (n <= 0 || !str)
+ return 0;
+
+ *dst = *str;
+
+ if (!*str)
+ return 0;
+ return 1;
+}
+
+#else
+
+int mbtowc(wchar_t *dst, const char *str, size_t n)
+{
+ if (n <= 0 || !str)
+ return 0;
+ if (!MultiByteToWideChar(CP_ACP, 0, str, n, dst, (dst == NULL) ? 0 : 1)) {
+ DWORD err = GetLastError();
+ switch (err) {
+ case ERROR_INSUFFICIENT_BUFFER:
+ break;
+ case ERROR_INVALID_FLAGS:
+ break;
+ case ERROR_INVALID_PARAMETER:
+ break;
+ case ERROR_NO_UNICODE_TRANSLATION:
+ break;
+ default:
+ return 1;
+ }
+ return -1;
+ }
+ /* return the number of bytes from src that have been used */
+ if (!*str)
+ return 0;
+ if (n >= 2 && isleadbyte(*str) && str[1])
+ return 2;
+ return 1;
+}
+
+#endif
--- /dev/null
+/* Copyright (C) 1991, 1992, 1995, 1996, 1997 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <windows.h>
+#include <msvcrt/stdlib.h>
+#include <msvcrt/ctype.h>
+#include <msvcrt/wchar.h>
+#include <msvcrt/errno.h>
+#include <msvcrt/internal/file.h>
+
+
+int
+STDCALL
+WideCharToMultiByte(
+ UINT CodePage,
+ DWORD dwFlags,
+ LPCWSTR lpWideCharStr,
+ int cchWideChar,
+ LPSTR lpMultiByteStr,
+ int cchMultiByte,
+ LPCSTR lpDefaultChar,
+ LPBOOL lpUsedDefaultChar);
+
+
+int wctomb(char* dst, wchar_t ch)
+{
+#if 0
+ return WideCharToMultiByte(CP_ACP, 0, &ch, 1, dst, 6, NULL, NULL);
+#else
+ if (dst == NULL) {
+ return 1;
+ }
+ *dst = ch;
+ return 1;
+#endif
+}
+
+
+#if 0
+
+#ifndef EILSEQ
+#define EILSEQ EINVAL
+#endif
+
+static const wchar_t encoding_mask[] =
+{
+ /* This reflects the sources *nix origin where type wchar_t
+ was 32 bits wide. Since our type wchar_t is only 16 bits
+ wide all this module will need to be reviewed.
+ Simplest option may well be to forward this modules work
+ on to the kernel which already has support for this.
+ */
+ ~0x7ff, ~0xffff, ~0x1fffff, ~0x3ffffff
+ //~0x0000-07ff, ~0x0000-ffff, ~0x001f-ffff, ~0x03ff-ffff
+};
+
+static const unsigned char encoding_byte[] =
+{
+ 0xc0, 0xe0, 0xf0, 0xf8, 0xfc
+};
+
+/* The state is for this UTF8 encoding not used. */
+//static mbstate_t internal;
+//extern mbstate_t __no_r_state; /* Defined in mbtowc.c. */
+
+size_t __wcrtomb(char *s, wchar_t wc);
+
+/* Convert WCHAR into its multibyte character representation,
+ putting this in S and returning its length.
+
+ Attention: this function should NEVER be intentionally used.
+ The interface is completely stupid. The state is shared between
+ all conversion functions. You should use instead the restartable
+ version `wcrtomb'. */
+
+int wctomb(char *s, wchar_t wchar)
+{
+ /* If S is NULL the function has to return null or not null
+ depending on the encoding having a state depending encoding or
+ not. This is nonsense because any multibyte encoding has a
+ state. The ISO C amendment 1 corrects this while introducing the
+ restartable functions. We simply say here all encodings have a
+ state. */
+ if (s == NULL) {
+ return 1;
+ }
+ return __wcrtomb(s, wchar);
+}
+
+size_t __wcrtomb(char *s, wchar_t wc)
+{
+ char fake[1];
+ size_t written = 0;
+
+ if (s == NULL) {
+ s = fake;
+ wc = L'\0';
+ }
+ /* Store the UTF8 representation of WC. */
+ //if (wc < 0 || wc > 0x7fffffff) {
+ if (wc < 0 || wc > 0x7fff) {
+ /* This is no correct ISO 10646 character. */
+ __set_errno (EILSEQ);
+ return (size_t) -1;
+ }
+ if (wc < 0x80) {
+ /* It's a one byte sequence. */
+ if (s != NULL) {
+ *s = (char)wc;
+ }
+ return 1;
+ }
+ for (written = 2; written < 6; ++written) {
+ if ((wc & encoding_mask[written - 2]) == 0) {
+ break;
+ }
+ }
+ if (s != NULL) {
+ size_t cnt = written;
+ s[0] = encoding_byte[cnt - 2];
+ --cnt;
+ do {
+ s[cnt] = 0x80 | (wc & 0x3f);
+ wc >>= 6;
+ } while (--cnt > 0);
+ s[0] |= wc;
+ }
+ return written;
+}
+
+#endif
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS system libraries
+ * FILE: lib/msvcrt/stdlib/fullpath.c
+ * PURPOSE: Gets the fullpathname
+ * PROGRAMER: Boudewijn Dekker
+ * UPDATE HISTORY:
+ * 28/12/98: Created
+ */
+#include <windows.h>
+#include <msvcrt/stdlib.h>
+
+
+wchar_t* _wfullpath(wchar_t* absPath, const wchar_t* relPath, size_t maxLength)
+{
+ wchar_t* lpFilePart;
+
+ if (GetFullPathNameW(relPath,maxLength,absPath,&lpFilePart) == 0)
+ return NULL;
+
+ return absPath;
+}
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS system libraries
+ * FILE: lib/msvcrt/stdlib/itoa.c
+ * PURPOSE: converts a integer to ascii
+ * PROGRAMER:
+ * UPDATE HISTORY:
+ * 1995: Created
+ * 1998: Added ltoa Boudewijn Dekker
+ */
+/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+
+#include <msvcrt/errno.h>
+#include <msvcrt/stdlib.h>
+#include <msvcrt/internal/file.h>
+
+
+char* _i64toa(__int64 value, char* string, int radix)
+{
+ char tmp[65];
+ char *tp = tmp;
+ int i;
+ unsigned v;
+ int sign;
+ char *sp;
+
+ if (radix > 36 || radix <= 1)
+ {
+ __set_errno(EDOM);
+ return 0;
+ }
+
+ sign = (radix == 10 && value < 0);
+ if (sign)
+ v = -value;
+ else
+ v = (unsigned)value;
+ while (v || tp == tmp)
+ {
+ i = v % radix;
+ v = v / radix;
+ if (i < 10)
+ *tp++ = i+'0';
+ else
+ *tp++ = i + 'a' - 10;
+ }
+
+ if (string == 0)
+ string = (char *)malloc((tp-tmp)+sign+1);
+ sp = string;
+
+ if (sign)
+ *sp++ = '-';
+ while (tp > tmp)
+ *sp++ = *--tp;
+ *sp = 0;
+ return string;
+}
+
+char* _ui64toa(unsigned __int64 value, char* string, int radix)
+{
+ char tmp[65];
+ char *tp = tmp;
+ long i;
+ unsigned long v = value;
+ char *sp;
+
+ if (radix > 36 || radix <= 1)
+ {
+ __set_errno(EDOM);
+ return 0;
+ }
+
+ while (v || tp == tmp)
+ {
+ i = v % radix;
+ v = v / radix;
+ if (i < 10)
+ *tp++ = i+'0';
+ else
+ *tp++ = i + 'a' - 10;
+ }
+
+ if (string == 0)
+ string = (char *)malloc((tp-tmp)+1);
+ sp = string;
+
+ while (tp > tmp)
+ *sp++ = *--tp;
+ *sp = 0;
+ return string;
+}
--- /dev/null
+/* $Id$
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS system libraries
+ * FILE: lib/msvcrt/stdlib/itow.c
+ * PURPOSE: converts a integer to wchar_t
+ * PROGRAMER:
+ * UPDATE HISTORY:
+ * 1995: Created
+ * 1998: Added ltoa Boudewijn Dekker
+ * 2000: derived from ./itoa.c by ea
+ */
+/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+
+#include <msvcrt/errno.h>
+#include <msvcrt/stdlib.h>
+#include <msvcrt/internal/file.h>
+
+
+wchar_t* _i64tow(__int64 value, wchar_t* string, int radix)
+{
+ wchar_t tmp[65];
+ wchar_t* tp = tmp;
+ int i;
+ unsigned v;
+ int sign;
+ wchar_t* sp;
+
+ if (radix > 36 || radix <= 1) {
+ __set_errno(EDOM);
+ return 0;
+ }
+
+ sign = (radix == 10 && value < 0);
+ if (sign)
+ v = -value;
+ else
+ v = (unsigned)value;
+ while (v || tp == tmp) {
+ i = v % radix;
+ v = v / radix;
+ if (i < 10)
+ *tp++ = i+L'0';
+ else
+ *tp++ = i + L'a' - 10;
+ }
+
+ if (string == 0)
+ string = (wchar_t*)malloc(((tp-tmp)+sign+1)*sizeof(wchar_t));
+ sp = string;
+
+ if (sign)
+ *sp++ = L'-';
+ while (tp > tmp)
+ *sp++ = *--tp;
+ *sp = 0;
+ return string;
+}
+
+wchar_t* _ui64tow(unsigned __int64 value, wchar_t* string, int radix)
+{
+ wchar_t tmp[65];
+ wchar_t* tp = tmp;
+ long i;
+ unsigned long v = value;
+ wchar_t* sp;
+
+ if (radix > 36 || radix <= 1) {
+ __set_errno(EDOM);
+ return 0;
+ }
+
+ while (v || tp == tmp) {
+ i = v % radix;
+ v = v / radix;
+ if (i < 10)
+ *tp++ = i+L'0';
+ else
+ *tp++ = i + L'a' - 10;
+ }
+
+ if (string == 0)
+ string = (wchar_t*)malloc(((tp-tmp)+1)*sizeof(wchar_t));
+ sp = string;
+
+ while (tp > tmp)
+ *sp++ = *--tp;
+ *sp = 0;
+ return string;
+}
--- /dev/null
+/* $Id$
+ */
+#include <msvcrt/stdlib.h>
+#include <msvcrt/string.h>
+
+
+void _wmakepath(wchar_t* path, const wchar_t* drive, const wchar_t* dir, const wchar_t* fname, const wchar_t* ext)
+{
+ int dir_len;
+
+ if ((drive != NULL) && (*drive)) {
+ wcscpy(path, drive);
+ wcscat(path, L":");
+ } else {
+ (*path) = 0;
+ }
+
+ if (dir != NULL) {
+ wcscat(path, dir);
+ dir_len = wcslen(dir);
+ if (dir_len && *(dir + dir_len - 1) != L'\\')
+ wcscat(path, L"\\");
+ }
+
+ if (fname != NULL) {
+ wcscat(path, fname);
+ if (ext != NULL && *ext != 0) {
+ if (*ext != L'.')
+ wcscat(path, L".");
+ wcscat(path, ext);
+ }
+ }
+}
--- /dev/null
+#include <windows.h>
+#include <msvcrt/stdlib.h>
+#include <msvcrt/string.h>
+
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+
+extern int BlockEnvToEnviron(); // defined in misc/dllmain.c
+
+int _wputenv(const wchar_t* val)
+{
+ wchar_t* buffer;
+ wchar_t* epos;
+ int res;
+
+ DPRINT("_wputenv('%S')\n", val);
+ epos = wcsrchr(val, L'=');
+ if (epos == NULL)
+ return -1;
+ buffer = (char*)malloc((epos - val + 1) * sizeof(wchar_t));
+ if (buffer == NULL)
+ return -1;
+ wcsncpy(buffer, val, epos - val);
+ buffer[epos - val] = 0;
+ res = SetEnvironmentVariableW(buffer, epos+1);
+ free(buffer);
+ if (BlockEnvToEnviron())
+ return 0;
+ return res;
+}
--- /dev/null
+#include <windows.h>
+#include <msvcrt/stdlib.h>
+#include <msvcrt/string.h>
+
+#define NDEBUG
+#include <msvcrt/msvcrtdbg.h>
+
+
+void _wsearchenv(const wchar_t* file,const wchar_t* var,wchar_t* path)
+{
+ wchar_t* env = _wgetenv(var);
+ wchar_t* x;
+ wchar_t* y;
+ wchar_t* FilePart;
+
+ DPRINT("_wsearchenv()\n");
+ x = wcschr(env,L'=');
+ if ( x != NULL ) {
+ *x = 0;
+ x++;
+ }
+ y = wcschr(env,L';');
+ while ( y != NULL ) {
+ *y = 0;
+ if ( SearchPathW(x,file,NULL,MAX_PATH,path,&FilePart) > 0 ) {
+ return;
+ }
+ x = y+1;
+ y = wcschr(env,L';');
+ }
+ return;
+}
--- /dev/null
+#include <msvcrt/stdlib.h>
+#include <msvcrt/string.h>
+
+
+void _wsplitpath(const wchar_t* path, wchar_t* drive, wchar_t* dir, wchar_t* fname, wchar_t* ext)
+{
+ wchar_t* tmp_drive;
+ wchar_t* tmp_dir;
+ wchar_t* tmp_ext;
+
+ tmp_drive = (wchar_t*)wcschr(path,L':');
+ if ( tmp_drive != (wchar_t*)NULL ) {
+ wcsncpy(drive,tmp_drive-1,1);
+ *(drive+1) = 0;
+ }
+ else {
+ *drive = 0;
+ tmp_drive = (wchar_t*)path;
+ }
+
+ tmp_dir = (wchar_t*)wcsrchr(path,L'\\');
+ if( tmp_dir != NULL && tmp_dir != tmp_drive + 1 ) {
+ wcsncpy(dir,tmp_drive+1,tmp_dir - tmp_drive);
+ *(dir + (tmp_dir - tmp_drive)) = 0;
+ }
+ else
+ *dir =0;
+
+ tmp_ext = (wchar_t*)wcsrchr(path,L'.');
+ if ( tmp_ext != NULL ) {
+ wcscpy(ext,tmp_ext);
+ }
+ else
+ {
+ *ext = 0;
+ tmp_ext = (wchar_t*)path+wcslen(path);
+ }
+
+ if ( tmp_dir != NULL ) {
+ wcsncpy(fname,tmp_dir+1,tmp_ext - tmp_dir - 1);
+ *(fname + (tmp_ext - tmp_dir -1)) = 0;
+ }
+ else
+ {
+ wcsncpy(fname,path,tmp_ext - path);
+ *(fname+(tmp_ext-path))=0;
+ }
+}
--- /dev/null
+#include <windows.h>
+#include <msvcrt/string.h>
+
+/* Compare S1 and S2, returning less than, equal to or
+ greater than zero if the collated form of S1 is lexicographically
+ less than, equal to or greater than the collated form of S2. */
+
+
+int _strncoll(const char* s1, const char* s2, size_t c)
+{
+ return strncmp(s1, s2, c);
+}
+
+int _strnicoll(const char* s1, const char* s2, size_t c)
+{
+ return _strnicmp(s1, s2, c);
+}
--- /dev/null
+/* $Id$
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS system libraries
+ * FILE: lib/msvcrt/sys/fstat.c
+ * PURPOSE: Gather file information
+ * PROGRAMER: Boudewijn Dekker
+ * UPDATE HISTORY:
+ * 28/12/98: Created
+ */
+#include <windows.h>
+#include <msvcrt/sys/types.h>
+#include <msvcrt/sys/stat.h>
+#include <msvcrt/fcntl.h>
+#include <msvcrt/string.h>
+#include <msvcrt/errno.h>
+#include <msvcrt/internal/file.h>
+
+
+__int64 _fstati64(int fd, struct _stati64* statbuf)
+{
+ BY_HANDLE_FILE_INFORMATION FileInformation;
+ DWORD dwFileType;
+ void *handle;
+
+ if (!statbuf)
+ {
+ __set_errno(EINVAL);
+ return -1;
+ }
+
+ if ((void*)-1 == (handle = _get_osfhandle(fd)))
+ {
+ __set_errno(EBADF);
+ return -1;
+ }
+
+ fflush(NULL);
+
+ memset(statbuf, 0, sizeof(struct _stati64));
+
+ dwFileType = GetFileType(handle);
+
+ if (dwFileType == FILE_TYPE_DISK)
+ {
+ if (!GetFileInformationByHandle(handle,&FileInformation))
+ {
+ __set_errno(EBADF);
+ return -1;
+ }
+ statbuf->st_ctime = FileTimeToUnixTime(&FileInformation.ftCreationTime,NULL);
+ statbuf->st_atime = FileTimeToUnixTime(&FileInformation.ftLastAccessTime,NULL);
+ statbuf->st_mtime = FileTimeToUnixTime(&FileInformation.ftLastWriteTime,NULL);
+
+ statbuf->st_dev = fd;
+ statbuf->st_size = (((__int64)FileInformation.nFileSizeHigh) << 32) +
+ FileInformation.nFileSizeLow;
+ statbuf->st_mode = S_IREAD;
+ if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ statbuf->st_mode |= S_IFDIR;
+ else
+ statbuf->st_mode |= S_IFREG;
+ if (!(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) statbuf->st_mode |= S_IWRITE;
+ }
+ else if (dwFileType == FILE_TYPE_CHAR)
+ {
+ statbuf->st_dev = fd;
+ statbuf->st_mode = S_IFCHR;
+ }
+ else if (dwFileType == FILE_TYPE_PIPE)
+ {
+ statbuf->st_dev = fd;
+ statbuf->st_mode = S_IFIFO;
+ }
+ else
+ {
+ // dwFileType is FILE_TYPE_UNKNOWN or has a bad value
+ __set_errno(EBADF);
+ return -1;
+ }
+ return 0;
+}
--- /dev/null
+#include <windows.h>
+#include <msvcrt/sys/types.h>
+#include <msvcrt/sys/stat.h>
+#include <msvcrt/fcntl.h>
+#include <msvcrt/io.h>
+#include <msvcrt/errno.h>
+#include <msvcrt/string.h>
+#include <msvcrt/internal/file.h>
+
+
+int _wstat (const wchar_t *path, struct stat *buffer)
+{
+ HANDLE findHandle;
+ WIN32_FIND_DATAW findData;
+
+ if (!buffer)
+ {
+ __set_errno(EINVAL);
+ return -1;
+ }
+
+ if(wcschr(path, L'*') || wcschr(path, L'?'))
+ {
+ __set_errno(EINVAL);
+ return -1;
+ }
+
+ findHandle = FindFirstFileW(path, &findData);
+ if (findHandle == INVALID_HANDLE_VALUE)
+ {
+ __set_errno(ENOENT);
+ return -1;
+ }
+
+ FindClose(findHandle);
+
+ memset (buffer, 0, sizeof(struct stat));
+
+ buffer->st_ctime = FileTimeToUnixTime(&findData.ftCreationTime,NULL);
+ buffer->st_atime = FileTimeToUnixTime(&findData.ftLastAccessTime,NULL);
+ buffer->st_mtime = FileTimeToUnixTime(&findData.ftLastWriteTime,NULL);
+
+// statbuf->st_dev = fd;
+ buffer->st_size = findData.nFileSizeLow;
+ buffer->st_mode = S_IREAD;
+ if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ buffer->st_mode |= S_IFDIR;
+ else
+ buffer->st_mode |= S_IFREG;
+ if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
+ buffer->st_mode |= S_IWRITE;
+
+ return 0;
+}
+
+__int64 _stati64 (const char *path, struct _stati64 *buffer)
+{
+ HANDLE findHandle;
+ WIN32_FIND_DATAA findData;
+
+ if (!buffer)
+ {
+ __set_errno(EINVAL);
+ return -1;
+ }
+
+ if(strchr(path, '*') || strchr(path, '?'))
+ {
+ __set_errno(EINVAL);
+ return -1;
+ }
+
+ findHandle = FindFirstFileA(path, &findData);
+ if (findHandle == INVALID_HANDLE_VALUE)
+ {
+ __set_errno(ENOENT);
+ return -1;
+ }
+
+ FindClose(findHandle);
+
+ memset (buffer, 0, sizeof(struct stat));
+
+ buffer->st_ctime = FileTimeToUnixTime(&findData.ftCreationTime,NULL);
+ buffer->st_atime = FileTimeToUnixTime(&findData.ftLastAccessTime,NULL);
+ buffer->st_mtime = FileTimeToUnixTime(&findData.ftLastWriteTime,NULL);
+
+// statbuf->st_dev = fd;
+ buffer->st_size = (((__int64)findData.nFileSizeHigh) << 32) +
+ findData.nFileSizeLow;
+ buffer->st_mode = S_IREAD;
+ if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ buffer->st_mode |= S_IFDIR;
+ else
+ buffer->st_mode |= S_IFREG;
+ if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
+ buffer->st_mode |= S_IWRITE;
+
+ return 0;
+}
+
+__int64 _wstati64 (const wchar_t *path, struct _stati64 *buffer)
+{
+ HANDLE findHandle;
+ WIN32_FIND_DATAW findData;
+
+ if (!buffer)
+ {
+ __set_errno(EINVAL);
+ return -1;
+ }
+
+ if(wcschr(path, L'*') || wcschr(path, L'?'))
+ {
+ __set_errno(EINVAL);
+ return -1;
+ }
+
+ findHandle = FindFirstFileW(path, &findData);
+ if (findHandle == INVALID_HANDLE_VALUE)
+ {
+ __set_errno(ENOENT);
+ return -1;
+ }
+
+ FindClose(findHandle);
+
+ memset (buffer, 0, sizeof(struct stat));
+
+ buffer->st_ctime = FileTimeToUnixTime(&findData.ftCreationTime,NULL);
+ buffer->st_atime = FileTimeToUnixTime(&findData.ftLastAccessTime,NULL);
+ buffer->st_mtime = FileTimeToUnixTime(&findData.ftLastWriteTime,NULL);
+
+// statbuf->st_dev = fd;
+ buffer->st_size = (((__int64)findData.nFileSizeHigh) << 32) +
+ findData.nFileSizeLow;
+ buffer->st_mode = S_IREAD;
+ if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ buffer->st_mode |= S_IFDIR;
+ else
+ buffer->st_mode |= S_IFREG;
+ if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
+ buffer->st_mode |= S_IWRITE;
+
+ return 0;
+}
--- /dev/null
+#include <msvcrt/string.h>
+#include <msvcrt/ctype.h>
+#include <msvcrt/stdlib.h>
+
+
+int _daylight;
+int _timezone;
+
+
+void _set_daylight_export(int value)
+{
+ _daylight = value;
+}
+
+void _set_timezone_export(int value)
+{
+ _timezone = value;
+}
+
+
+
--- /dev/null
+/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
+/* This file has been modified by DJ Delorie. These modifications are
+** Copyright (C) 1995 DJ Delorie, 24 Kirsten Ave, Rochester NH,
+** 03867-2954, USA.
+*/
+
+/*
+ * Copyright (c) 1987, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Arthur David Olson of the National Cancer Institute.
+ *
+ * Redistribution and use in source and binary forms are permitted provided
+ * that: (1) source distributions retain this entire copyright notice and
+ * comment, and (2) distributions including binaries display the following
+ * acknowledgement: ``This product includes software developed by the
+ * University of California, Berkeley and its contributors'' in the
+ * documentation or other materials provided with the distribution and in
+ * all advertising materials mentioning features or use of this software.
+ * Neither the name of the University nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <msvcrt/fcntl.h>
+#include <msvcrt/time.h>
+#include <windows.h>
+#include "tzfile.h"
+
+
+wchar_t* _wasctime(const struct tm* timeptr)
+{
+#ifdef __GNUC__
+ static const wchar_t wday_name[DAYSPERWEEK][3] = {
+ L"Sun", L"Mon", L"Tue", L"Wed", L"Thu", L"Fri", L"Sat"
+ };
+ static const wchar_t mon_name[MONSPERYEAR][3] = {
+ L"Jan", L"Feb", L"Mar", L"Apr", L"May", L"Jun",
+ L"Jul", L"Aug", L"Sep", L"Oct", L"Nov", L"Dec"
+ };
+#else
+ static const wchar_t wday_name[DAYSPERWEEK][4] = {
+ L"Sun", L"Mon", L"Tue", L"Wed", L"Thu", L"Fri", L"Sat"
+ };
+ static const wchar_t mon_name[MONSPERYEAR][4] = {
+ L"Jan", L"Feb", L"Mar", L"Apr", L"May", L"Jun",
+ L"Jul", L"Aug", L"Sep", L"Oct", L"Nov", L"Dec"
+ };
+#endif
+ static wchar_t result[26];
+
+ (void)swprintf(result, L"%.3s %.3s%3d %02d:%02d:%02d %d\n",
+ wday_name[timeptr->tm_wday],
+ mon_name[timeptr->tm_mon],
+ timeptr->tm_mday, timeptr->tm_hour,
+ timeptr->tm_min, timeptr->tm_sec,
+ TM_YEAR_BASE + timeptr->tm_year);
+ return result;
+}
+
+
+wchar_t* _wctime(const time_t* const timep)
+{
+ return _wasctime(localtime(timep));
+}
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS system libraries
+ * FILE: lib/msvcrt/time/strtime.c
+ * PURPOSE: Fills a buffer with a formatted date representation
+ * PROGRAMER: Boudewijn Dekker
+ * UPDATE HISTORY:
+ * 28/12/98: Created
+ */
+#include <msvcrt/time.h>
+#include <msvcrt/stdio.h>
+#include <msvcrt/errno.h>
+#include <msvcrt/internal/file.h>
+
+
+wchar_t* _wstrdate(const wchar_t* datestr)
+{
+ time_t t;
+ struct tm* d;
+ wchar_t* dt = (wchar_t*)datestr;
+
+ if (datestr == NULL) {
+ __set_errno(EINVAL);
+ return NULL;
+ }
+ t = time(NULL);
+ d = localtime(&t);
+ swprintf(dt,L"%d/%d/%d",d->tm_mday,d->tm_mon+1,d->tm_year);
+ return dt;
+}
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS system libraries
+ * FILE: lib/msvcrt/time/strtime.c
+ * PURPOSE: Fills a buffer with a formatted time representation
+ * PROGRAMER: Boudewijn Dekker
+ * UPDATE HISTORY:
+ * 28/12/98: Created
+ */
+#include <msvcrt/time.h>
+#include <msvcrt/stdio.h>
+#include <msvcrt/errno.h>
+#include <msvcrt/internal/file.h>
+
+
+wchar_t* _wstrtime(wchar_t* buf)
+{
+ time_t t;
+ struct tm* d;
+ wchar_t* dt = (wchar_t*)buf;
+
+ if ( buf == NULL ) {
+ __set_errno(EINVAL);
+ return NULL;
+ }
+ t = time(NULL);
+ d = localtime(&t);
+ swprintf(dt,L"%d:%d:%d",d->tm_hour,d->tm_min,d->tm_sec);
+ return dt;
+}
--- /dev/null
+/* $Id$
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: lib/ntdll/ldr/res.c
+ * PURPOSE: Resource access for PE executables
+ * PROGRAMMERS: Jean Michault
+ * Rex Jolliff (rex@lvcablemodem.com)
+ * Robert Dickenson (robd@mok.lvcm.com)
+ */
+
+/*
+ * TODO:
+ * - any comments ??
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <reactos/config.h>
+#include <ddk/ntddk.h>
+#include <windows.h>
+#include <string.h>
+#include <wchar.h>
+#include <ntdll/ldr.h>
+#include <ntos/minmax.h>
+
+#define NDEBUG
+#include <ntdll/ntdll.h>
+
+/* PROTOTYPES ****************************************************************/
+
+
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ Status = LdrFindResource_U (hModule,
+ &ResourceInfo,
+ RESOURCE_DATA_LEVEL,
+ &ResourceDataEntry);
+ */
+NTSTATUS STDCALL
+LdrFindResource_U(PVOID BaseAddress,
+ PLDR_RESOURCE_INFO ResourceInfo,
+ ULONG Level,
+ PIMAGE_RESOURCE_DATA_ENTRY* ResourceDataEntry)
+{
+ PIMAGE_RESOURCE_DIRECTORY ResDir;
+ PIMAGE_RESOURCE_DIRECTORY ResBase;
+ PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG EntryCount;
+ PWCHAR ws;
+ ULONG i;
+ ULONG Id;
+
+ //DPRINT("LdrFindResource_U()\n");
+ DPRINT("LdrFindResource_U(%08x, %08x, %d, %08x)\n", BaseAddress, ResourceInfo, Level, ResourceDataEntry);
+
+ /* Get the pointer to the resource directory */
+ ResDir = (PIMAGE_RESOURCE_DIRECTORY)RtlImageDirectoryEntryToData(BaseAddress,
+ TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &i);
+ if (ResDir == NULL) {
+ return STATUS_RESOURCE_DATA_NOT_FOUND;
+ }
+
+ DPRINT("ResourceDirectory: %x Size: %d\n", (ULONG)ResDir, (int)i);
+
+ ResBase = ResDir;
+
+ /* Let's go into resource tree */
+ for (i = 0; i < Level; i++) {
+ DPRINT("ResDir: %x Level: %d\n", (ULONG)ResDir, i);
+
+ Id = ((PULONG)ResourceInfo)[i];
+// ResourceInfo.Type = (ULONG)lpType;
+// ResourceInfo.Name = (ULONG)lpName;
+// ResourceInfo.Language = (ULONG)wLanguage;
+
+ EntryCount = ResDir->NumberOfNamedEntries;
+ DPRINT(" Id: %d NumberOfNamedEntries: %d\n", Id, EntryCount);
+ ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1);
+ //DPRINT("ResEntry %x\n", (ULONG)ResEntry);
+ if (Id & 0xFFFF0000) {
+ /* Resource name is a unicode string */
+ DPRINT("ResEntry %x - Resource name is a unicode string\n", (ULONG)ResEntry);
+ DPRINT("EntryCount %d\n", (ULONG)EntryCount);
+ for (; EntryCount--; ResEntry++) {
+ /* Scan entries for equal name */
+ if (ResEntry->Name & 0x80000000) {
+ ws = (PWCHAR)((ULONG)ResDir + (ResEntry->Name & 0x7FFFFFFF));
+ if (!wcsncmp((PWCHAR)Id, ws + 1, *ws) &&
+ wcslen((PWCHAR)Id) == (int)*ws) {
+ goto found;
+ }
+ }
+ }
+ } else {
+ /* We use ID number instead of string */
+ DPRINT("ResEntry %x - Resource ID number instead of string\n", (ULONG)ResEntry);
+ DPRINT("EntryCount %d\n", (ULONG)EntryCount);
+ ResEntry += EntryCount;
+ EntryCount = ResDir->NumberOfIdEntries;
+ DPRINT("EntryCount %d\n", (ULONG)EntryCount);
+ for (; EntryCount--; ResEntry++) {
+ /* Scan entries for equal name */
+ DPRINT("EntryCount %d ResEntry %x\n", (ULONG)EntryCount, ResEntry);
+ DPRINT("ResEntry->Name %x Id %x\n", (ULONG)ResEntry->Name, Id);
+ if (ResEntry->Name == Id) {
+ DPRINT("ID entry found %x\n", Id);
+ goto found;
+ }
+ }
+ }
+
+ //DPRINT("Error %lu\n", i);
+
+ switch (i) {
+ case 0:
+ DPRINT("Error %lu - STATUS_RESOURCE_TYPE_NOT_FOUND\n", i);
+ return STATUS_RESOURCE_TYPE_NOT_FOUND;
+ case 1:
+ DPRINT("Error %lu - STATUS_RESOURCE_NAME_NOT_FOUND\n", i);
+ return STATUS_RESOURCE_NAME_NOT_FOUND;
+ case 2:
+ if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries) {
+ /* Use the first available language */
+ ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1);
+ break;
+ }
+ DPRINT("Error %lu - STATUS_RESOURCE_LANG_NOT_FOUND\n", i);
+ return STATUS_RESOURCE_LANG_NOT_FOUND;
+ case 3:
+ DPRINT("Error %lu - STATUS_RESOURCE_DATA_NOT_FOUND\n", i);
+ return STATUS_RESOURCE_DATA_NOT_FOUND;
+ default:
+ DPRINT("Error %lu - STATUS_INVALID_PARAMETER\n", i);
+ return STATUS_INVALID_PARAMETER;
+ }
+found:;
+ ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResBase +
+ (ResEntry->OffsetToData & 0x7FFFFFFF));
+ }
+ DPRINT("ResourceDataEntry: %x\n", (ULONG)ResDir);
+
+ if (ResourceDataEntry) {
+ *ResourceDataEntry = (PVOID)ResDir;
+ }
+ return Status;
+}
+
+
+NTSTATUS STDCALL
+LdrAccessResource(IN PVOID BaseAddress,
+ IN PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry,
+ OUT PVOID* Resource OPTIONAL,
+ OUT PULONG Size OPTIONAL)
+{
+ PIMAGE_SECTION_HEADER Section;
+ PIMAGE_NT_HEADERS NtHeader;
+ ULONG SectionRva;
+ ULONG SectionVa;
+ ULONG DataSize;
+ ULONG Offset = 0;
+ ULONG Data;
+
+ Data = (ULONG)RtlImageDirectoryEntryToData(BaseAddress,
+ TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &DataSize);
+ if (Data == 0) {
+ return STATUS_RESOURCE_DATA_NOT_FOUND;
+ }
+ if ((ULONG)BaseAddress & 1) {
+ /* loaded as ordinary file */
+ NtHeader = RtlImageNtHeader((PVOID)((ULONG)BaseAddress & ~1UL));
+ Offset = (ULONG)BaseAddress - Data + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
+ Section = RtlImageRvaToSection(NtHeader, BaseAddress, NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress);
+ if (Section == NULL) {
+ return STATUS_RESOURCE_DATA_NOT_FOUND;
+ }
+ if (Section->Misc.VirtualSize < ResourceDataEntry->OffsetToData) {
+ SectionRva = RtlImageRvaToSection (NtHeader, BaseAddress, ResourceDataEntry->OffsetToData)->VirtualAddress;
+ SectionVa = RtlImageRvaToVa(NtHeader, BaseAddress, SectionRva, NULL);
+ Offset = SectionRva - SectionVa + Data - Section->VirtualAddress;
+ }
+ }
+ if (Resource) {
+ *Resource = (PVOID)(ResourceDataEntry->OffsetToData - Offset + (ULONG)BaseAddress);
+ }
+ if (Size) {
+ *Size = ResourceDataEntry->Size;
+ }
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS STDCALL
+LdrFindResourceDirectory_U(IN PVOID BaseAddress,
+ WCHAR** name,
+ DWORD level,
+ OUT PVOID* addr)
+{
+ PIMAGE_RESOURCE_DIRECTORY ResDir;
+ PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
+ ULONG EntryCount;
+ ULONG i;
+ NTSTATUS Status = STATUS_SUCCESS;
+ WCHAR* ws;
+
+ /* Get the pointer to the resource directory */
+ ResDir = (PIMAGE_RESOURCE_DIRECTORY)
+ RtlImageDirectoryEntryToData(BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &i);
+ if (ResDir == NULL) {
+ return STATUS_RESOURCE_DATA_NOT_FOUND;
+ }
+
+ /* Let's go into resource tree */
+ for (i = 0; i < level; i++, name++) {
+ EntryCount = ResDir->NumberOfNamedEntries;
+ ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1);
+ if ((ULONG)(*name) & 0xFFFF0000) {
+ /* Resource name is a unicode string */
+ for (; EntryCount--; ResEntry++) {
+ /* Scan entries for equal name */
+ if (ResEntry->Name & 0x80000000) {
+ ws = (WCHAR*)((ULONG)ResDir + (ResEntry->Name & 0x7FFFFFFF));
+ if (!wcsncmp(*name, ws + 1, *ws) && wcslen(*name) == (int)*ws) {
+ goto found;
+ }
+ }
+ }
+ } else {
+ /* We use ID number instead of string */
+ ResEntry += EntryCount;
+ EntryCount = ResDir->NumberOfIdEntries;
+ for (; EntryCount--; ResEntry++) {
+ /* Scan entries for equal name */
+ if (ResEntry->Name == (ULONG)(*name))
+ goto found;
+ }
+ }
+ switch (i) {
+ case 0:
+ return STATUS_RESOURCE_TYPE_NOT_FOUND;
+ case 1:
+ return STATUS_RESOURCE_NAME_NOT_FOUND;
+ case 2:
+ Status = STATUS_RESOURCE_LANG_NOT_FOUND;
+ /* Just use first language entry */
+ if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries) {
+ ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1);
+ break;
+ }
+ return Status;
+ case 3:
+ return STATUS_RESOURCE_DATA_NOT_FOUND;
+ default:
+ return STATUS_INVALID_PARAMETER;
+ }
+found:;
+ ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResDir + ResEntry->OffsetToData);
+ }
+ if (addr) {
+ *addr = (PVOID)ResDir;
+ }
+ return Status;
+}
+
+/* EOF */
--- /dev/null
+control.exe
+control.coff
+control.sym
+control.dsp
+control.dsw
+*.o
--- /dev/null
+#
+# ReactOS control
+#
+# Makefile
+#
+# Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+PATH_TO_TOP = ..
+
+TARGET = control
+
+BASE_CFLAGS = -DGCC -D_WIN32_IE=0x0400 -DUNICODE -D_UNICODE
+
+RCFLAGS = -DGCC -D_WIN32_IE=0x0400
+
+
+OBJS = framewnd.o \
+ listview.o \
+ main.o
+
+LIBS = -lgdi32 -luser32 -lkernel32 -lcomctl32
+
+all: $(TARGET).exe
+
+$(TARGET).res: $(TARGET).rc
+
+$(TARGET).exe: $(OBJS) $(TARGET).coff
+ $(CC) -Wl,--subsystem,windows -o $(TARGET).exe $(OBJS) $(TARGET).coff $(LIBS)
+ $(NM) --numeric-sort $(TARGET).exe > $(TARGET).sym
+
+
+main.h: resource.h
+
+main.o: main.c main.h framewnd.h
+
+framewnd.o: framewnd.c framewnd.h listview.h main.h
+
+listview.o: listview.c listview.h main.h
+
+about.o: about.c about.h main.h
+
+
+clean:
+ - $(RM) $(OBJS)
+ - $(RM) $(TARGET).exe
+ - $(RM) $(TARGET).sym
+ - $(RM) $(TARGET).coff
+
+include $(PATH_TO_TOP)/rules.mak
--- /dev/null
+*.sym
+*.coff
+*.dll
+*.o
--- /dev/null
+# $Id$
+
+PATH_TO_TOP = ../..
+
+TARGET_DEFONLY = yes
+
+TARGET_TYPE = dynlink
+
+TARGET_NAME = winedbgc
+
+#TARGET_CFLAGS = -fno-rtti -D_ROS_ -D__WINE__
+
+#TARGET_CFLAGS = -g -D__NTDLL__
+TARGET_CFLAGS = -D__NTDLL__
+
+TARGET_LFLAGS = -Wl,--file-alignment,0x1000 \
+ -Wl,--section-alignment,0x1000 \
+ -nostartfiles
+
+TARGET_BASE = 0x77a90000
+
+TARGET_SDKLIBS = ntdll.a kernel32.a
+
+TARGET_OBJECTS = \
+ debug.o \
+ libmain.o \
+ porting.o \
+ winedbgc.o \
+ winedbgc.dll.dbg.o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# EOF
--- /dev/null
+/*
+ * Management of the debugging channels
+ *
+ * Copyright 2000 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 <ntddk.h>
+#include <wine/debugtools.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+ */
+#include <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "porting.h"
+/*
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "wine/debug.h"
+#include "wine/library.h"
+#include "wine/unicode.h"
+ */
+struct dll
+{
+ struct dll *next; /* linked list of dlls */
+ struct dll *prev;
+ char * const *channels; /* array of channels */
+ int nb_channels; /* number of channels in array */
+};
+
+static struct dll *first_dll;
+
+struct debug_option
+{
+ struct debug_option *next; /* next option in list */
+ unsigned char set; /* bits to set */
+ unsigned char clear; /* bits to clear */
+ char name[14]; /* channel name, or empty for "all" */
+};
+
+static struct debug_option *first_option;
+static struct debug_option *last_option;
+
+static const char * const debug_classes[] = { "fixme", "err", "warn", "trace" };
+
+static int cmp_name( const void *p1, const void *p2 )
+{
+ const char *name = p1;
+ const char * const *chan = p2;
+ return strcmp( name, *chan + 1 );
+}
+
+/* apply a debug option to the channels of a given dll */
+static void apply_option( struct dll *dll, const struct debug_option *opt )
+{
+ if (opt->name[0])
+ {
+ char **dbch = bsearch( opt->name, dll->channels, dll->nb_channels,
+ sizeof(*dll->channels), cmp_name );
+ if (dbch) **dbch = (**dbch & ~opt->clear) | opt->set;
+ }
+ else /* all */
+ {
+ int i;
+ for (i = 0; i < dll->nb_channels; i++)
+ dll->channels[i][0] = (dll->channels[i][0] & ~opt->clear) | opt->set;
+ }
+}
+
+/* register a new set of channels for a dll */
+void *__wine_dbg_register( char * const *channels, int nb )
+{
+ struct debug_option *opt = first_option;
+ struct dll *dll = malloc( sizeof(*dll) );
+ if (dll)
+ {
+ dll->channels = channels;
+ dll->nb_channels = nb;
+ dll->prev = NULL;
+ if ((dll->next = first_dll)) dll->next->prev = dll;
+ first_dll = dll;
+
+ /* apply existing options to this dll */
+ while (opt)
+ {
+ apply_option( dll, opt );
+ opt = opt->next;
+ }
+ }
+ return dll;
+}
+
+
+/* unregister a set of channels; must pass the pointer obtained from wine_dbg_register */
+void __wine_dbg_unregister( void *channel )
+{
+ struct dll *dll = channel;
+ if (dll)
+ {
+ if (dll->next) dll->next->prev = dll->prev;
+ if (dll->prev) dll->prev->next = dll->next;
+ else first_dll = dll->next;
+ free( dll );
+ }
+}
+
+
+/* add a new debug option at the end of the option list */
+void wine_dbg_add_option( const char *name, unsigned char set, unsigned char clear )
+{
+ struct dll *dll = first_dll;
+ struct debug_option *opt;
+
+ if (!(opt = malloc( sizeof(*opt) ))) return;
+ opt->next = NULL;
+ opt->set = set;
+ opt->clear = clear;
+ strncpy( opt->name, name, sizeof(opt->name) );
+ opt->name[sizeof(opt->name)-1] = 0;
+ if (last_option) last_option->next = opt;
+ else first_option = opt;
+ last_option = opt;
+
+ /* apply option to all existing dlls */
+ while (dll)
+ {
+ apply_option( dll, opt );
+ dll = dll->next;
+ }
+}
+
+/* parse a set of debugging option specifications and add them to the option list */
+int wine_dbg_parse_options( const char *str )
+{
+ char *p, *opt, *next, *options;
+ int i, errors = 0;
+
+ if (!(options = strdup(str))) return -1;
+ for (opt = options; opt; opt = next)
+ {
+ unsigned char set = 0, clear = 0;
+
+ if ((next = strchr( opt, ',' ))) *next++ = 0;
+
+ p = opt + strcspn( opt, "+-" );
+ if (!p[0] || !p[1]) /* bad option, skip it */
+ {
+ errors++;
+ continue;
+ }
+
+ if (p > opt)
+ {
+ for (i = 0; i < sizeof(debug_classes)/sizeof(debug_classes[0]); i++)
+ {
+ int len = strlen(debug_classes[i]);
+ if (len != (p - opt)) continue;
+ if (!memcmp( opt, debug_classes[i], len )) /* found it */
+ {
+ if (*p == '+') set |= 1 << i;
+ else clear |= 1 << i;
+ break;
+ }
+ }
+ if (i == sizeof(debug_classes)/sizeof(debug_classes[0])) /* bad class name, skip it */
+ {
+ errors++;
+ continue;
+ }
+ }
+ else
+ {
+ if (*p == '+') set = ~0;
+ else clear = ~0;
+ }
+ p++;
+ if (!strcmp( p, "all" )) p = ""; /* empty string means all */
+ wine_dbg_add_option( p, set, clear );
+ }
+ free( options );
+ return errors;
+}
+
+#ifdef __WINE__
+
+/* varargs wrapper for __wine_dbg_vprintf */
+int wine_dbg_printf( const char *format, ... )
+{
+ int ret;
+ va_list valist;
+
+ va_start(valist, format);
+ ret = __wine_dbg_vprintf( format, valist );
+ va_end(valist);
+ return ret;
+}
+
+
+/* varargs wrapper for __wine_dbg_vlog */
+int wine_dbg_log( int cls, const char *channel, const char *func, const char *format, ... )
+{
+ int ret;
+ va_list valist;
+
+ va_start(valist, format);
+ ret = __wine_dbg_vlog( cls, channel, func, format, valist );
+ va_end(valist);
+ return ret;
+}
+
+#endif /*__WINE__*/
+
+/* allocate some tmp string space */
+/* FIXME: this is not 100% thread-safe */
+static char *get_tmp_space( int size )
+{
+ static char *list[32];
+ static long pos;
+ char *ret;
+ int idx;
+
+ idx = interlocked_xchg_add( &pos, 1 ) % (sizeof(list)/sizeof(list[0]));
+ if ((ret = realloc( list[idx], size ))) list[idx] = ret;
+ return ret;
+}
+
+
+/* default implementation of wine_dbgstr_an */
+static const char *default_dbgstr_an( const char *str, int n )
+{
+ char *dst, *res;
+
+ if (!HIWORD(str))
+ {
+ if (!str) return "(null)";
+ res = get_tmp_space( 6 );
+ sprintf( res, "#%04x", LOWORD(str) );
+ return res;
+ }
+ if (n == -1) n = strlen(str);
+ if (n < 0) n = 0;
+ else if (n > 200) n = 200;
+ dst = res = get_tmp_space( n * 4 + 6 );
+ *dst++ = '"';
+ while (n-- > 0)
+ {
+ unsigned char c = *str++;
+ switch (c)
+ {
+ case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
+ case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
+ case '\t': *dst++ = '\\'; *dst++ = 't'; break;
+ case '"': *dst++ = '\\'; *dst++ = '"'; break;
+ case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
+ default:
+ if (c >= ' ' && c <= 126)
+ *dst++ = c;
+ else
+ {
+ *dst++ = '\\';
+ *dst++ = '0' + ((c >> 6) & 7);
+ *dst++ = '0' + ((c >> 3) & 7);
+ *dst++ = '0' + ((c >> 0) & 7);
+ }
+ }
+ }
+ *dst++ = '"';
+ if (*str)
+ {
+ *dst++ = '.';
+ *dst++ = '.';
+ *dst++ = '.';
+ }
+ *dst = 0;
+ return res;
+}
+
+
+/* default implementation of wine_dbgstr_wn */
+static const char *default_dbgstr_wn( const WCHAR *str, int n )
+{
+ char *dst, *res;
+
+ if (!HIWORD(str))
+ {
+ if (!str) return "(null)";
+ res = get_tmp_space( 6 );
+ sprintf( res, "#%04x", LOWORD(str) );
+ return res;
+ }
+ if (n == -1) n = strlenW(str);
+ if (n < 0) n = 0;
+ else if (n > 200) n = 200;
+ dst = res = get_tmp_space( n * 5 + 7 );
+ *dst++ = 'L';
+ *dst++ = '"';
+ while (n-- > 0)
+ {
+ WCHAR c = *str++;
+ switch (c)
+ {
+ case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
+ case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
+ case '\t': *dst++ = '\\'; *dst++ = 't'; break;
+ case '"': *dst++ = '\\'; *dst++ = '"'; break;
+ case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
+ default:
+ if (c >= ' ' && c <= 126)
+ *dst++ = c;
+ else
+ {
+ *dst++ = '\\';
+ sprintf(dst,"%04x",c);
+ dst+=4;
+ }
+ }
+ }
+ *dst++ = '"';
+ if (*str)
+ {
+ *dst++ = '.';
+ *dst++ = '.';
+ *dst++ = '.';
+ }
+ *dst = 0;
+ return res;
+}
+
+
+/* default implementation of wine_dbgstr_guid */
+static const char *default_dbgstr_guid( const struct _GUID *id )
+{
+ char *str;
+
+ if (!id) return "(null)";
+ if (!((int)id >> 16))
+ {
+ str = get_tmp_space( 12 );
+ sprintf( str, "<guid-0x%04x>", (int)id & 0xffff );
+ }
+ else
+ {
+ str = get_tmp_space( 40 );
+ sprintf( str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+ id->Data1, id->Data2, id->Data3,
+ id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
+ id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
+ }
+ return str;
+}
+
+
+/* default implementation of wine_dbg_vprintf */
+static int default_dbg_vprintf( const char *format, va_list args )
+{
+ return vfprintf( stderr, format, args );
+}
+
+
+/* default implementation of wine_dbg_vlog */
+static int default_dbg_vlog( int cls, const char *channel, const char *func,
+ const char *format, va_list args )
+{
+ int ret = 0;
+
+ if (cls < sizeof(debug_classes)/sizeof(debug_classes[0]))
+ ret += wine_dbg_printf( "%s:%s:%s ", debug_classes[cls], channel + 1, func );
+ if (format)
+ ret += __wine_dbg_vprintf( format, args );
+ return ret;
+}
+
+
+/* exported function pointers so that debugging functions can be redirected at run-time */
+
+const char * (*__wine_dbgstr_an)( const char * s, int n ) = default_dbgstr_an;
+const char * (*__wine_dbgstr_wn)( const WCHAR *s, int n ) = default_dbgstr_wn;
+const char * (*__wine_dbgstr_guid)( const struct _GUID *id ) = default_dbgstr_guid;
+int (*__wine_dbg_vprintf)( const char *format, va_list args ) = default_dbg_vprintf;
+int (*__wine_dbg_vlog)( int cls, const char *channel, const char *function,
+ const char *format, va_list args ) = default_dbg_vlog;
+
+/* wrappers to use the function pointers */
+
+#ifdef __WINE__
+
+const char *wine_dbgstr_guid( const struct _GUID *id )
+{
+ return __wine_dbgstr_guid(id);
+}
+
+const char *wine_dbgstr_an( const char * s, int n )
+{
+ return __wine_dbgstr_an(s, n);
+}
+
+const char *wine_dbgstr_wn( const WCHAR *s, int n )
+{
+ return __wine_dbgstr_wn(s, n);
+}
+
+const char *wine_dbgstr_a( const char *s )
+{
+ return __wine_dbgstr_an( s, -1 );
+}
+
+const char *wine_dbgstr_w( const WCHAR *s )
+{
+ return __wine_dbgstr_wn( s, -1 );
+}
+
+#endif /*__WINE__*/
--- /dev/null
+/*
+ * Win32 winedbgc functions
+ *
+ *
+ * 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 <windows.h>
+//#include <ntddk.h>
+//#include <wine/debugtools.h>
+//#include <stdlib.h>
+//#include <stdio.h>
+//#include <stdarg.h>
+//#include <string.h>
+//#include <ctype.h>
+/*
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "winbase.h"
+#include "wine/debug.h"
+#include "wine/library.h"
+
+#include "proxywinedbgc.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(winedbgc);
+ */
+
+/***********************************************************************
+ * DllMain [Internal] Initializes the internal 'winedbgc32.DLL'.
+ *
+ * PARAMS
+ * hinstDLL [I] handle to the DLL's instance
+ * fdwReason [I]
+ * lpvReserved [I] reserved, must be NULL
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ */
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+// TRACE("Initializing or Finalizing winedbgc: %p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
+ if (fdwReason == DLL_PROCESS_ATTACH)
+ {
+// TRACE("Loading winedbgc...\n");
+/*
+#ifndef __REACTOS__
+ if (winedbgc_LoadDriverManager())
+ winedbgc_LoadDMFunctions();
+#endif
+ */
+ }
+ else if (fdwReason == DLL_PROCESS_DETACH)
+ {
+// TRACE("Unloading winedbgc...\n");
+/*
+#ifndef __REACTOS__
+ if (gProxyHandle.bFunctionReady)
+ {
+ int i;
+ for ( i = 0; i < NUM_SQLFUNC; i ++ )
+ {
+ gProxyHandle.functions[i].func = SQLDummyFunc;
+ }
+ }
+ if (gProxyHandle.dmHandle)
+ {
+ wine_dlclose(gProxyHandle.dmHandle,NULL,0);
+ gProxyHandle.dmHandle = NULL;
+ }
+#endif
+ */
+ }
+ return TRUE;
+}
+
+
+/* EOF */
--- /dev/null
+/*
+ * Porting wine comtrl32 to ReactOS comctrl32 support functions
+ *
+ * Copyright 2002 Robert Dickenson
+ *
+ * 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 <windows.h>
+#include "porting.h"
+
+
+static int interlocked_mutex;
+void _lwp_mutex_lock(int* interlocked_mutex) {}
+void _lwp_mutex_unlock(int* interlocked_mutex) {}
+
+long interlocked_xchg_add( long *dest, long incr )
+{
+ long retv;
+ _lwp_mutex_lock( &interlocked_mutex );
+ retv = *dest;
+ *dest += incr;
+ _lwp_mutex_unlock( &interlocked_mutex );
+ return retv;
+}
+
--- /dev/null
+/*
+ * Porting from wine to ReactOS definitions
+ *
+ * Copyright 2002 Robert Dickenson
+ *
+ * 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
+ */
+
+#ifndef __PORTING_WINE2ROS_H
+#define __PORTING_WINE2ROS_H
+
+
+#ifndef __GNUC__
+#define inline _inline
+#endif
+
+long interlocked_xchg_add(long *dest, long incr);
+
+#define strlenW wcslen
+
+#define strstrW wcsstr
+#define strtolW wcstol
+#define strncasecmp strncmp
+#define snprintf _snprintf
+#define strcasecmp _stricmp
+
+
+#endif /* __PORTING_WINE2ROS_H */
--- /dev/null
+/*
+ * Debugging channels functions for WINE
+ */
+#include <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "porting.h"
+
+//#include <ntddk.h>
+#include <wine/debugtools.h>
+
+//DECLARE_DEBUG_CHANNEL(tid);
+DECLARE_DEBUG_CHANNEL(winedbgc);
+
+
+/* ---------------------------------------------------------------------- */
+
+struct debug_info
+{
+ char *str_pos; /* current position in strings buffer */
+ char *out_pos; /* current position in output buffer */
+ char strings[1024]; /* buffer for temporary strings */
+ char output[1024]; /* current output line */
+};
+
+static struct debug_info tmp;
+
+/* get the debug info pointer for the current thread */
+static inline struct debug_info *get_info(void)
+{
+ struct debug_info *info = NtCurrentTeb()->WineDebugInfo;
+ if (!info)
+ {
+ if (!tmp.str_pos)
+ {
+ tmp.str_pos = tmp.strings;
+ tmp.out_pos = tmp.output;
+ }
+ if (!RtlGetProcessHeap()) return &tmp;
+ /* setup the temp structure in case HeapAlloc wants to print something */
+ NtCurrentTeb()->WineDebugInfo = &tmp;
+ info = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*info) );
+ info->str_pos = info->strings;
+ info->out_pos = info->output;
+ NtCurrentTeb()->WineDebugInfo = info;
+ }
+ return info;
+}
+
+/* allocate some tmp space for a string */
+static void *gimme1(int n)
+{
+ struct debug_info *info = get_info();
+ char *res = info->str_pos;
+
+ if (res + n >= &info->strings[sizeof(info->strings)]) res = info->strings;
+ info->str_pos = res + n;
+ return res;
+}
+
+/* release extra space that we requested in gimme1() */
+static inline void release( void *ptr )
+{
+ struct debug_info *info = NtCurrentTeb()->WineDebugInfo;
+ info->str_pos = ptr;
+}
+
+/***********************************************************************
+ * wine_dbgstr_an (NTDLL.@)
+ */
+const char *wine_dbgstr_an( const char *src, int n )
+{
+ char *dst, *res;
+
+ if (!((WORD)(DWORD)(src) >> 16))
+ {
+ if (!src) return "(null)";
+ res = gimme1(6);
+ sprintf(res, "#%04x", (WORD)(DWORD)(src) );
+ return res;
+ }
+ if (n < 0) n = 0;
+ else if (n > 200) n = 200;
+ dst = res = gimme1 (n * 4 + 6);
+ *dst++ = '"';
+ while (n-- > 0 && *src)
+ {
+ unsigned char c = *src++;
+ switch (c)
+ {
+ case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
+ case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
+ case '\t': *dst++ = '\\'; *dst++ = 't'; break;
+ case '"': *dst++ = '\\'; *dst++ = '"'; break;
+ case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
+ default:
+ if (c >= ' ' && c <= 126)
+ *dst++ = c;
+ else
+ {
+ *dst++ = '\\';
+ *dst++ = '0' + ((c >> 6) & 7);
+ *dst++ = '0' + ((c >> 3) & 7);
+ *dst++ = '0' + ((c >> 0) & 7);
+ }
+ }
+ }
+ *dst++ = '"';
+ if (*src)
+ {
+ *dst++ = '.';
+ *dst++ = '.';
+ *dst++ = '.';
+ }
+ *dst++ = '\0';
+ release( dst );
+ return res;
+}
+
+/***********************************************************************
+ * wine_dbgstr_wn (NTDLL.@)
+ */
+const char *wine_dbgstr_wn( const WCHAR *src, int n )
+{
+ char *dst, *res;
+
+ if (!((WORD)(DWORD)(src) >> 16))
+ {
+ if (!src) return "(null)";
+ res = gimme1(6);
+ sprintf(res, "#%04x", (WORD)(DWORD)(src) );
+ return res;
+ }
+ if (n < 0) n = 0;
+ else if (n > 200) n = 200;
+ dst = res = gimme1 (n * 5 + 7);
+ *dst++ = 'L';
+ *dst++ = '"';
+ while (n-- > 0 && *src)
+ {
+ WCHAR c = *src++;
+ switch (c)
+ {
+ case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
+ case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
+ case '\t': *dst++ = '\\'; *dst++ = 't'; break;
+ case '"': *dst++ = '\\'; *dst++ = '"'; break;
+ case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
+ default:
+ if (c >= ' ' && c <= 126)
+ *dst++ = c;
+ else
+ {
+ *dst++ = '\\';
+ sprintf(dst,"%04x",c);
+ dst+=4;
+ }
+ }
+ }
+ *dst++ = '"';
+ if (*src)
+ {
+ *dst++ = '.';
+ *dst++ = '.';
+ *dst++ = '.';
+ }
+ *dst++ = '\0';
+ release( dst );
+ return res;
+}
+
+/***********************************************************************
+ * wine_dbgstr_guid (NTDLL.@)
+ */
+const char *wine_dbgstr_guid( const GUID *id )
+{
+ char *str;
+
+ if (!id) return "(null)";
+ if (!((WORD)(DWORD)(id) >> 16))
+ {
+ str = gimme1(12);
+ sprintf( str, "<guid-0x%04x>", (WORD)(DWORD)(id) );
+ }
+ else
+ {
+ str = gimme1(40);
+ sprintf( str, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+ id->Data1, id->Data2, id->Data3,
+ id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
+ id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
+ }
+ return str;
+}
+
+/***********************************************************************
+ * wine_dbg_vprintf (NTDLL.@)
+ */
+int wine_dbg_vprintf( const char *format, va_list args )
+{
+ struct debug_info *info = get_info();
+ char *p;
+
+ int ret = _vsnprintf( info->out_pos, sizeof(info->output) - (info->out_pos - info->output),
+ format, args );
+
+ p = strrchr( info->out_pos, '\n' );
+ if (!p) info->out_pos += ret;
+ else
+ {
+ char *pos = info->output;
+ char saved_ch;
+ p++;
+ saved_ch = *p;
+ *p = 0;
+ DbgPrint(pos);
+ *p = saved_ch;
+ /* move beginning of next line to start of buffer */
+ while ((*pos = *p++)) pos++;
+ info->out_pos = pos;
+ }
+ return ret;
+}
+
+/***********************************************************************
+ * wine_dbg_printf (NTDLL.@)
+ */
+int wine_dbg_printf(const char *format, ...)
+{
+ int ret;
+ va_list valist;
+
+ va_start(valist, format);
+ ret = wine_dbg_vprintf( format, valist );
+ va_end(valist);
+ return ret;
+}
+
+/***********************************************************************
+ * wine_dbg_log (NTDLL.@)
+ */
+int wine_dbg_log(enum __DEBUG_CLASS cls, const char *channel,
+ const char *function, const char *format, ... )
+{
+ static const char *classes[__DBCL_COUNT] = { "fixme", "err", "warn", "trace" };
+ va_list valist;
+ int ret = 0;
+
+ va_start(valist, format);
+ if (TRACE_ON(winedbgc))
+ ret = wine_dbg_printf( "%08lx:", NtCurrentTeb()->Cid.UniqueThread);
+ if (cls < __DBCL_COUNT)
+ ret += wine_dbg_printf( "%s:%s:%s ", classes[cls], channel + 1, function );
+ if (format)
+ ret += wine_dbg_vprintf( format, valist );
+ va_end(valist);
+ return ret;
+}
--- /dev/null
+; $Id$
+;
+; ReactOS Operating System
+;
+LIBRARY winedbgc.dll
+
+EXPORTS
+
+wine_dbg_log
+wine_dbg_printf
+wine_dbgstr_an
+wine_dbgstr_guid
+wine_dbgstr_wn
+__wine_dbg_register
+__wine_dbg_unregister
+__wine_dbg_vlog DATA
+__wine_dbg_vprintf DATA
+__wine_dbgstr_an DATA
+__wine_dbgstr_guid DATA
+__wine_dbgstr_wn DATA
+
+
+;
+;wine_dbg_log @1
+;__wine_dbg_register @2
+;__wine_dbg_unregister @3
+;__wine_dbg_vlog @4 DATA
+;__wine_dbg_vprintf @5 DATA
+;__wine_dbgstr_an @6 DATA
+;__wine_dbgstr_guid @7 DATA
+;__wine_dbgstr_wn @8 DATA
+;
+;wine_dbg_printf @34
+;wine_dbgstr_an @36
+;wine_dbgstr_guid @37
+;wine_dbgstr_wn @39
+;
\ No newline at end of file
--- /dev/null
+/* File generated automatically; do not edit! */
+/* This file can be copied, modified and distributed without restriction. */
+
+char __wine_dbch_winedbgc[] = "\003winedbgc";
+
+static char * const debug_channels[4] =
+{
+ __wine_dbch_winedbgc
+};
+
+static void *debug_registration;
+
+#ifdef __GNUC__
+static void __wine_dbg_winedbgc32_init(void) __attribute__((constructor));
+static void __wine_dbg_winedbgc32_fini(void) __attribute__((destructor));
+#else
+static void __asm__dummy_dll_init(void) {
+asm("\t.section\t\".init\" ,\"ax\"\n"
+ "\tcall ___wine_dbg_winedbgc32_init\n"
+ "\t.section\t\".fini\" ,\"ax\"\n"
+ "\tcall ___wine_dbg_winedbgc32_fini\n"
+ "\t.section\t\".text\"\n");
+}
+#endif /* defined(__GNUC__) */
+
+#ifdef __GNUC__
+static
+#endif
+void __wine_dbg_winedbgc32_init(void)
+{
+// extern void *__wine_dbg_register( char * const *, int );
+// debug_registration = __wine_dbg_register( debug_channels, 4 );
+}
+
+#ifdef __GNUC__
+static
+#endif
+void __wine_dbg_winedbgc32_fini(void)
+{
+// extern void __wine_dbg_unregister( void* );
+// __wine_dbg_unregister( debug_registration );
+}
--- /dev/null
+; $Id$
+;
+; ReactOS Operating System
+;
+LIBRARY winedbgc.dll
+
+EXPORTS
+
+wine_dbg_log
+wine_dbg_printf
+wine_dbgstr_an
+wine_dbgstr_guid
+wine_dbgstr_wn
+__wine_dbg_register
+__wine_dbg_unregister
+__wine_dbg_vlog DATA
+__wine_dbg_vprintf DATA
+__wine_dbgstr_an DATA
+__wine_dbgstr_guid DATA
+__wine_dbgstr_wn DATA
+
+
+
+;wine_dbgstr_an
+;wine_dbgstr_wn
+;wine_dbgstr_guid
+;wine_dbg_vprintf
+;wine_dbg_printf
+;wine_dbg_log
+
+; wine_dbg_log @1
+; __wine_dbg_register @2
+; __wine_dbg_unregister @3
+; __wine_dbg_vlog @4 DATA
+; __wine_dbg_vprintf @5 DATA
+; __wine_dbgstr_an @6 DATA
+; __wine_dbgstr_guid @7 DATA
+; __wine_dbgstr_wn @8 DATA
+;__wine_dll_register @9
+;__wine_main_argc @10 DATA
+;__wine_main_argv @11 DATA
+;__wine_main_wargv @12 DATA
+
+
+;interlocked_cmpxchg @20
+;interlocked_cmpxchg_ptr @21
+;interlocked_xchg @22
+;interlocked_xchg_add @23
+;interlocked_xchg_ptr @24
+;wine_anon_mmap @30
+;wine_dbg_add_option @31
+;wine_dbg_parse_options @33
+; wine_dbg_printf @34
+;wine_dbgstr_a @35
+; wine_dbgstr_an @36
+; wine_dbgstr_guid @37
+;wine_dbgstr_w @38
+; wine_dbgstr_wn @39
+;wine_dlclose @40
+;wine_dll_load @41
+;wine_dll_load_main_exe @42
+;wine_dll_set_callback @43
+;wine_dll_unload @44
+;wine_dlopen @45
+;wine_dlsym @46
+;wine_errno_location @47 DATA
+;wine_get_config_dir @48
+;wine_get_cs @49
+;wine_get_ds @50
+;wine_get_es @51
+;wine_get_fs @52
+;wine_get_gs @53
+;wine_get_server_dir @54
+;wine_get_ss @55
+;wine_h_errno_location @56 DATA
+;wine_ldt_copy @57 DATA
+;wine_ldt_get_entry @58
+;wine_ldt_set_entry @59
+;wine_rewrite_s4tos2 @60
+;wine_set_fs @61
+;wine_set_gs @62
--- /dev/null
+#include <defines.h>
+#include <reactos/resource.h>
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
+ PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", RES_STR_COMPANY_NAME
+ VALUE "FileDescription", "WINE debug channels for ReactOS\0"
+ VALUE "FileVersion", RES_STR_FILE_VERSION
+ VALUE "InternalName", "winedbgc\0"
+ VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
+ VALUE "OriginalFilename", "winedbgc.dll\0"
+ VALUE "ProductName", RES_STR_PRODUCT_NAME
+ VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 1998-2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ *
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/dbg/profile.c
+ * PURPOSE: Kernel profiling
+ * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * UPDATE HISTORY:
+ * Created 12/01/2003
+ */
+
+/* INCLUDES *****************************************************************/
+
+#define NTOS_MODE_KERNEL
+#include <ntos.h>
+#include <internal/ldr.h>
+#include "kdb.h"
+
+#define NDEBUG
+#include <internal/debug.h>
+
+/* FUNCTIONS *****************************************************************/
+
+#define PROFILE_SESSION_LENGTH 30 /* Session length in seconds */
+
+typedef struct _PROFILE_DATABASE_ENTRY
+{
+ ULONG_PTR Address;
+} PROFILE_DATABASE_ENTRY, *PPROFILE_DATABASE_ENTRY;
+
+#define PDE_BLOCK_ENTRIES ((PAGE_SIZE - (sizeof(LIST_ENTRY) + sizeof(ULONG))) / sizeof(PROFILE_DATABASE_ENTRY))
+
+typedef struct _PROFILE_DATABASE_BLOCK
+{
+ LIST_ENTRY ListEntry;
+ ULONG UsedEntries;
+ PROFILE_DATABASE_ENTRY Entries[PDE_BLOCK_ENTRIES];
+} PROFILE_DATABASE_BLOCK, *PPROFILE_DATABASE_BLOCK;
+
+typedef struct _PROFILE_DATABASE
+{
+ LIST_ENTRY ListHead;
+} PROFILE_DATABASE, *PPROFILE_DATABASE;
+
+typedef struct _SAMPLE_GROUP_INFO
+{
+ ULONG_PTR Address;
+ ULONG Count;
+ CHAR Description[128];
+ LIST_ENTRY ListEntry;
+} SAMPLE_GROUP_INFO, *PSAMPLE_GROUP_INFO;
+
+static volatile BOOLEAN KdbProfilingInitialized = FALSE;
+static volatile BOOLEAN KdbProfilingEnabled = FALSE;
+static volatile BOOLEAN KdbProfilingSuspended = FALSE;
+static PPROFILE_DATABASE KdbProfileDatabase = NULL;
+static KDPC KdbProfilerCollectorDpc;
+static HANDLE KdbProfilerThreadHandle;
+static CLIENT_ID KdbProfilerThreadCid;
+static HANDLE KdbProfilerLogFile;
+static KTIMER KdbProfilerTimer;
+static KMUTEX KdbProfilerLock;
+static BOOLEAN KdbEnableProfiler = FALSE;
+
+VOID
+KdbDeleteProfileDatabase(PPROFILE_DATABASE ProfileDatabase)
+{
+ PLIST_ENTRY current = NULL;
+
+ current = RemoveHeadList(&ProfileDatabase->ListHead);
+ while (current != &ProfileDatabase->ListHead)
+ {
+ PPROFILE_DATABASE_BLOCK block = CONTAINING_RECORD(
+ current, PROFILE_DATABASE_BLOCK, ListEntry);
+ ExFreePool(block);
+ current = RemoveHeadList(&ProfileDatabase->ListHead);
+ }
+}
+
+VOID
+KdbAddEntryToProfileDatabase(PPROFILE_DATABASE ProfileDatabase, ULONG_PTR Address)
+{
+ PPROFILE_DATABASE_BLOCK block;
+
+ if (IsListEmpty(&ProfileDatabase->ListHead))
+ {
+ block = ExAllocatePool(NonPagedPool, sizeof(PROFILE_DATABASE_BLOCK));
+ assert(block);
+ block->UsedEntries = 0;
+ InsertTailList(&ProfileDatabase->ListHead, &block->ListEntry);
+ block->Entries[block->UsedEntries++].Address = Address;
+ return;
+ }
+
+ block = CONTAINING_RECORD(ProfileDatabase->ListHead.Blink, PROFILE_DATABASE_BLOCK, ListEntry);
+ if (block->UsedEntries >= PDE_BLOCK_ENTRIES)
+ {
+ block = ExAllocatePool(NonPagedPool, sizeof(PROFILE_DATABASE_BLOCK));
+ assert(block);
+ block->UsedEntries = 0;
+ InsertTailList(&ProfileDatabase->ListHead, &block->ListEntry);
+ }
+ block->Entries[block->UsedEntries++].Address = Address;
+}
+
+VOID
+KdbInitProfiling()
+{
+ KdbEnableProfiler = TRUE;
+}
+
+VOID
+KdbInitProfiling2()
+{
+ if (KdbEnableProfiler)
+ {
+ KdbEnableProfiling();
+ KdbProfilingInitialized = TRUE;
+ }
+}
+
+VOID
+KdbSuspendProfiling()
+{
+ KdbProfilingSuspended = TRUE;
+}
+
+VOID
+KdbResumeProfiling()
+{
+ KdbProfilingSuspended = FALSE;
+}
+
+BOOLEAN
+KdbProfilerGetSymbolInfo(PVOID address, OUT PCH NameBuffer)
+{
+ PLIST_ENTRY current_entry;
+ MODULE_TEXT_SECTION* current;
+ extern LIST_ENTRY ModuleTextListHead;
+ ULONG_PTR RelativeAddress;
+ NTSTATUS Status;
+ ULONG LineNumber;
+ CHAR FileName[256];
+ CHAR FunctionName[256];
+
+ current_entry = ModuleTextListHead.Flink;
+
+ while (current_entry != &ModuleTextListHead &&
+ current_entry != NULL)
+ {
+ current =
+ CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
+
+ if (address >= (PVOID)current->Base &&
+ address < (PVOID)(current->Base + current->Length))
+ {
+ RelativeAddress = (ULONG_PTR) address - current->Base;
+ Status = LdrGetAddressInformation(¤t->SymbolInfo,
+ RelativeAddress,
+ &LineNumber,
+ FileName,
+ FunctionName);
+ if (NT_SUCCESS(Status))
+ {
+ sprintf(NameBuffer, "%s (%s)", FileName, FunctionName);
+ return(TRUE);
+ }
+ return(TRUE);
+ }
+ current_entry = current_entry->Flink;
+ }
+ return(FALSE);
+}
+
+PLIST_ENTRY
+KdbProfilerLargestSampleGroup(PLIST_ENTRY SamplesListHead)
+{
+ PLIST_ENTRY current;
+ PLIST_ENTRY largest;
+ ULONG count;
+
+ count = 0;
+ largest = SamplesListHead->Flink;
+ current = SamplesListHead->Flink;
+ while (current != SamplesListHead)
+ {
+ PSAMPLE_GROUP_INFO sgi = CONTAINING_RECORD(
+ current, SAMPLE_GROUP_INFO, ListEntry);
+
+ if (sgi->Count > count)
+ {
+ largest = current;
+ count = sgi->Count;
+ }
+
+ current = current->Flink;
+ }
+ if (count == 0)
+ {
+ return NULL;
+ }
+ return largest;
+}
+
+VOID
+KdbProfilerWriteString(PCH String)
+{
+ IO_STATUS_BLOCK Iosb;
+ NTSTATUS Status;
+ ULONG Length;
+
+ Length = strlen(String);
+ Status = NtWriteFile(KdbProfilerLogFile,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ String,
+ Length,
+ NULL,
+ NULL);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtWriteFile() failed with status 0x%.08x\n", Status);
+ }
+}
+
+NTSTATUS
+KdbProfilerWriteSampleGroups(PLIST_ENTRY SamplesListHead)
+{
+ CHAR Buffer[256];
+ PLIST_ENTRY current = NULL;
+ PLIST_ENTRY Largest;
+
+ KdbProfilerWriteString("\r\n\r\n");
+ KdbProfilerWriteString("Count Symbol\n");
+ KdbProfilerWriteString("--------------------------------------------------\r\n");
+
+ current = SamplesListHead->Flink;
+ while (current != SamplesListHead)
+ {
+ Largest = KdbProfilerLargestSampleGroup(SamplesListHead);
+ if (Largest != NULL)
+ {
+ PSAMPLE_GROUP_INFO sgi = CONTAINING_RECORD(
+ Largest, SAMPLE_GROUP_INFO, ListEntry);
+
+ //DbgPrint("%.08d %s\n", sgi->Count, sgi->Description);
+
+ sprintf(Buffer, "%.08d %s\r\n", sgi->Count, sgi->Description);
+ KdbProfilerWriteString(Buffer);
+
+ RemoveEntryList(Largest);
+ ExFreePool(sgi);
+ }
+ else
+ {
+ break;
+ }
+
+ current = SamplesListHead->Flink;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+LONG STDCALL
+KdbProfilerKeyCompare(IN PVOID Key1,
+ IN PVOID Key2)
+{
+ int value = strcmp(Key1, Key2);
+
+ if (value == 0)
+ return 0;
+
+ return (value < 0) ? -1 : 1;
+}
+
+
+NTSTATUS
+KdbProfilerAnalyzeSamples()
+{
+ CHAR NameBuffer[512];
+ ULONG KeyLength;
+ PLIST_ENTRY current = NULL;
+ HASH_TABLE Hashtable;
+ LIST_ENTRY SamplesListHead;
+ ULONG Index;
+ ULONG_PTR Address;
+
+ if (!ExInitializeHashTable(&Hashtable, 17, KdbProfilerKeyCompare, TRUE))
+ {
+ DPRINT1("ExInitializeHashTable() failed.");
+ KeBugCheck(0);
+ }
+
+ InitializeListHead(&SamplesListHead);
+
+ current = RemoveHeadList(&KdbProfileDatabase->ListHead);
+ while (current != &KdbProfileDatabase->ListHead)
+ {
+ PPROFILE_DATABASE_BLOCK block;
+
+ block = CONTAINING_RECORD(current, PROFILE_DATABASE_BLOCK, ListEntry);
+
+ for (Index = 0; Index < block->UsedEntries; Index++)
+ {
+ PSAMPLE_GROUP_INFO sgi;
+ Address = block->Entries[Index].Address;
+ if (KdbProfilerGetSymbolInfo((PVOID) Address, (PCH) &NameBuffer))
+ {
+ }
+ else
+ {
+ sprintf(NameBuffer, "(0x%.08x)", (ULONG) Address);
+ }
+
+ KeyLength = strlen(NameBuffer);
+ if (!ExSearchHashTable(&Hashtable, (PVOID) NameBuffer, KeyLength, (PVOID *) &sgi))
+ {
+ sgi = ExAllocatePool(NonPagedPool, sizeof(SAMPLE_GROUP_INFO));
+ assert(sgi);
+ sgi->Address = Address;
+ sgi->Count = 1;
+ strcpy(sgi->Description, NameBuffer);
+ InsertTailList(&SamplesListHead, &sgi->ListEntry);
+ ExInsertHashTable(&Hashtable, sgi->Description, KeyLength, (PVOID) sgi);
+ }
+ else
+ {
+ sgi->Count++;
+ }
+ }
+
+ ExFreePool(block);
+
+ current = RemoveHeadList(&KdbProfileDatabase->ListHead);
+ }
+
+ KdbProfilerWriteSampleGroups(&SamplesListHead);
+
+ ExDeleteHashTable(&Hashtable);
+
+ KdbDeleteProfileDatabase(KdbProfileDatabase);
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS STDCALL
+KdbProfilerThreadMain(PVOID Context)
+{
+ for (;;)
+ {
+ KeWaitForSingleObject(&KdbProfilerTimer, Executive, KernelMode, TRUE, NULL);
+
+ KeWaitForSingleObject(&KdbProfilerLock, Executive, KernelMode, FALSE, NULL);
+
+ KdbSuspendProfiling();
+
+ KdbProfilerAnalyzeSamples();
+
+ KdbResumeProfiling();
+
+ KeReleaseMutex(&KdbProfilerLock, FALSE);
+ }
+}
+
+VOID
+KdbDisableProfiling()
+{
+ if (KdbProfilingEnabled == TRUE)
+ {
+ /* FIXME: Implement */
+#if 0
+ KdbProfilingEnabled = FALSE;
+ /* Stop timer */
+ /* Close file */
+ if (KdbProfileDatabase != NULL)
+ {
+ KdbDeleteProfileDatabase(KdbProfileDatabase);
+ ExFreePool(KdbProfileDatabase);
+ KdbProfileDatabase = NULL;
+ }
+#endif
+ }
+}
+
+/*
+ * SystemArgument1 = EIP
+ */
+static VOID STDCALL
+KdbProfilerCollectorDpcRoutine(PKDPC Dpc, PVOID DeferredContext,
+ PVOID SystemArgument1, PVOID SystemArgument2)
+{
+ ULONG_PTR address = (ULONG_PTR) SystemArgument1;
+
+ KdbAddEntryToProfileDatabase(KdbProfileDatabase, address);
+}
+
+VOID
+KdbEnableProfiling()
+{
+ if (KdbProfilingEnabled == FALSE)
+ {
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING FileName;
+ IO_STATUS_BLOCK Iosb;
+ LARGE_INTEGER DueTime;
+
+ RtlInitUnicodeString(&FileName, L"\\SystemRoot\\profiler.log");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &FileName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&KdbProfilerLogFile,
+ FILE_ALL_ACCESS,
+ &ObjectAttributes,
+ &Iosb,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_SUPERSEDE,
+ FILE_WRITE_THROUGH | FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create profiler log file\n");
+ return;
+ }
+
+ Status = PsCreateSystemThread(&KdbProfilerThreadHandle,
+ THREAD_ALL_ACCESS,
+ NULL,
+ NULL,
+ &KdbProfilerThreadCid,
+ KdbProfilerThreadMain,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create profiler thread\n");
+ return;
+ }
+
+ KeInitializeMutex(&KdbProfilerLock, 0);
+
+ KdbProfileDatabase = ExAllocatePool(NonPagedPool, sizeof(PROFILE_DATABASE));
+ assert(KdbProfileDatabase);
+ InitializeListHead(&KdbProfileDatabase->ListHead);
+ KeInitializeDpc(&KdbProfilerCollectorDpc, KdbProfilerCollectorDpcRoutine, NULL);
+
+ /* Initialize our periodic timer and its associated DPC object. When the timer
+ expires, the KdbProfilerSessionEndDpc deferred procedure call (DPC) is queued */
+ KeInitializeTimerEx(&KdbProfilerTimer, SynchronizationTimer);
+
+ /* Start the periodic timer with an initial and periodic
+ relative expiration time of PROFILE_SESSION_LENGTH seconds */
+ DueTime.QuadPart = -(LONGLONG) PROFILE_SESSION_LENGTH * 1000 * 10000;
+ KeSetTimerEx(&KdbProfilerTimer, DueTime, PROFILE_SESSION_LENGTH * 1000, NULL);
+
+ KdbProfilingEnabled = TRUE;
+ }
+}
+
+VOID
+KdbProfileInterrupt(ULONG_PTR Address)
+{
+ assert(KeGetCurrentIrql() == PROFILE_LEVEL);
+
+ if (KdbProfilingInitialized != TRUE)
+ {
+ return;
+ }
+
+ if ((KdbProfilingEnabled) && (!KdbProfilingSuspended))
+ {
+ (BOOLEAN) KeInsertQueueDpc(&KdbProfilerCollectorDpc, (PVOID) Address, NULL);
+ }
+}
--- /dev/null
+/* $Id$
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: kernel/rtl/math.c
+ * PURPOSE:
+ * UPDATE HISTORY:
+ * Created 20/12/2002
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+
+/* FUNCTIONS *****************************************************************/
+
+LARGE_INTEGER
+STDCALL
+_alldiv(ULONG UnsignedInteger)
+{
+ LARGE_INTEGER RC;
+
+ RC.QuadPart = 0;
+ return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+_allmul(ULONG UnsignedInteger)
+{
+ LARGE_INTEGER RC;
+
+ RC.QuadPart = 0;
+ return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+_allrem(ULONG UnsignedInteger)
+{
+ LARGE_INTEGER RC;
+
+ RC.QuadPart = 0;
+ return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+_allshl(ULONG UnsignedInteger)
+{
+ LARGE_INTEGER RC;
+
+ RC.QuadPart = 0;
+ return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+_allshr(ULONG UnsignedInteger)
+{
+ LARGE_INTEGER RC;
+
+ RC.QuadPart = 0;
+ return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+_aulldiv(ULONG UnsignedInteger)
+{
+ LARGE_INTEGER RC;
+
+ RC.QuadPart = 0;
+ return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+_aullrem(ULONG UnsignedInteger)
+{
+ LARGE_INTEGER RC;
+
+ RC.QuadPart = 0;
+ return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+_aullshr(ULONG UnsignedInteger)
+{
+ LARGE_INTEGER RC;
+
+ RC.QuadPart = 0;
+ return RC;
+}
+
+
+/*
+LARGE_INTEGER
+STDCALL
+RtlConvertLongToLargeInteger (
+ LONG SignedInteger
+ )
+{
+ LARGE_INTEGER RC;
+
+ RC.QuadPart = SignedInteger;
+
+ return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlConvertUlongToLargeInteger (
+ ULONG UnsignedInteger
+ )
+{
+ LARGE_INTEGER RC;
+
+ RC.QuadPart = UnsignedInteger;
+
+ return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlEnlargedIntegerMultiply (
+ LONG Multiplicand,
+ LONG Multiplier
+ )
+{
+ LARGE_INTEGER RC;
+
+ RC.QuadPart = (LONGLONG) Multiplicand * Multiplier;
+
+ return RC;
+}
+
+ULONG
+STDCALL
+RtlEnlargedUnsignedDivide (
+ ULARGE_INTEGER Dividend,
+ ULONG Divisor,
+ PULONG Remainder
+ )
+{
+ if (Remainder)
+ *Remainder = Dividend.QuadPart % Divisor;
+
+ return (ULONG)(Dividend.QuadPart / Divisor);
+}
+
+LARGE_INTEGER
+STDCALL
+RtlEnlargedUnsignedMultiply (
+ ULONG Multiplicand,
+ ULONG Multiplier
+ )
+{
+ LARGE_INTEGER RC;
+
+ RC.QuadPart = (ULONGLONG) Multiplicand * Multiplier;
+
+ return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlExtendedIntegerMultiply (
+ LARGE_INTEGER Multiplicand,
+ LONG Multiplier
+ )
+{
+ LARGE_INTEGER RC;
+
+ RC.QuadPart = Multiplicand.QuadPart * Multiplier;
+
+ return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlExtendedLargeIntegerDivide (
+ LARGE_INTEGER Dividend,
+ ULONG Divisor,
+ PULONG Remainder
+ )
+{
+ LARGE_INTEGER RC;
+
+ if (Remainder)
+ *Remainder = Dividend.QuadPart % Divisor;
+
+ RC.QuadPart = Dividend.QuadPart / Divisor;
+
+ return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlExtendedMagicDivide (LARGE_INTEGER Dividend,
+ LARGE_INTEGER MagicDivisor,
+ CCHAR ShiftCount)
+{
+ LARGE_INTEGER Result;
+
+ Result.QuadPart = (Dividend.QuadPart * MagicDivisor.QuadPart) >> ShiftCount;
+ return(Result);
+}
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerAdd (
+ LARGE_INTEGER Addend1,
+ LARGE_INTEGER Addend2
+ )
+{
+ LARGE_INTEGER RC;
+
+ RC.QuadPart = Addend1.QuadPart + Addend2.QuadPart;
+
+ return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerArithmeticShift (
+ LARGE_INTEGER LargeInteger,
+ CCHAR ShiftCount
+ )
+{
+ LARGE_INTEGER RC;
+ CHAR Shift;
+
+ Shift = ShiftCount % 64;
+
+ if (Shift < 32)
+ {
+ RC.QuadPart = LargeInteger.QuadPart >> Shift;
+ }
+ else
+ {
+ // copy the sign bit
+ RC.u.HighPart |= (LargeInteger.u.HighPart & 0x80000000);
+ RC.u.LowPart = LargeInteger.u.HighPart >> Shift;
+ }
+
+ return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerDivide (
+ LARGE_INTEGER Dividend,
+ LARGE_INTEGER Divisor,
+ PLARGE_INTEGER Remainder
+ )
+{
+ LARGE_INTEGER RC;
+
+ if (Remainder)
+ Remainder->QuadPart = Dividend.QuadPart % Divisor.QuadPart;
+
+ RC.QuadPart = Dividend.QuadPart / Divisor.QuadPart;
+
+ return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerNegate (
+ LARGE_INTEGER Subtrahend
+ )
+{
+ LARGE_INTEGER RC;
+
+ RC.QuadPart = - Subtrahend.QuadPart;
+
+ return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerShiftLeft (
+ LARGE_INTEGER LargeInteger,
+ CCHAR ShiftCount
+ )
+{
+ LARGE_INTEGER RC;
+ CHAR Shift;
+
+ Shift = ShiftCount % 64;
+ RC.QuadPart = LargeInteger.QuadPart << Shift;
+
+ return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerShiftRight (
+ LARGE_INTEGER LargeInteger,
+ CCHAR ShiftCount
+ )
+{
+ LARGE_INTEGER RC;
+ CHAR Shift;
+
+ Shift = ShiftCount % 64;
+ RC.QuadPart = LargeInteger.QuadPart >> ShiftCount;
+
+ return RC;
+}
+
+LARGE_INTEGER
+STDCALL
+RtlLargeIntegerSubtract (
+ LARGE_INTEGER Minuend,
+ LARGE_INTEGER Subtrahend
+ )
+{
+ LARGE_INTEGER RC;
+
+ RC.QuadPart = Minuend.QuadPart - Subtrahend.QuadPart;
+
+ return RC;
+}
+ */
+/* EOF */
--- /dev/null
+; $Id$
+;
+
+LIBRARY csrss.exe
+
+EXPORTS
+
+CsrServerInitialization
--- /dev/null
+; $Id$
+;
+;
+
+LIBRARY csrss.exe
+
+EXPORTS
+
+CsrServerInitialization=CsrServerInitialization@8
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2002 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS text-mode setup
+ * FILE: subsys/system/usetup/bootsup.c
+ * PURPOSE: Bootloader support functions
+ * PROGRAMMER: Eric Kohl
+ */
+
+#include <ddk/ntddk.h>
+#include <ntdll/rtl.h>
+
+#include "usetup.h"
+#include "inicache.h"
+#include "bootsup.h"
+
+
+#define SECTORSIZE 512
+
+/* FUNCTIONS ****************************************************************/
+
+
+static VOID
+CreateCommonFreeLoaderSections(PINICACHE IniCache)
+{
+ PINICACHESECTION IniSection;
+
+ /* Create "FREELOADER" section */
+ IniSection = IniCacheAppendSection(IniCache,
+ L"FREELOADER");
+
+ /* DefaultOS=ReactOS */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"DefaultOS",
+ L"ReactOS");
+
+#if 0
+ /* Timeout=10 */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"TimeOut",
+ L"10");
+#endif
+
+ /* Create "Display" section */
+ IniSection = IniCacheAppendSection(IniCache,
+ L"Display");
+
+ /* TitleText=ReactOS Boot Manager */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"TitleText",
+ L"ReactOS Boot Manager");
+
+ /* StatusBarColor=Cyan */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"StatusBarColor",
+ L"Cyan");
+
+ /* StatusBarTextColor=Black */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"StatusBarTextColor",
+ L"Black");
+
+ /* BackdropTextColor=White */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"BackdropTextColor",
+ L"White");
+
+ /* BackdropColor=Blue */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"BackdropColor",
+ L"Blue");
+
+ /* BackdropFillStyle=Medium */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"BackdropFillStyle",
+ L"Medium");
+
+ /* TitleBoxTextColor=White */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"TitleBoxTextColor",
+ L"White");
+
+ /* TitleBoxColor=Red */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"TitleBoxColor",
+ L"Red");
+
+ /* MessageBoxTextColor=White */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"MessageBoxTextColor",
+ L"White");
+
+ /* MessageBoxColor=Blue */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"MessageBoxColor",
+ L"Blue");
+
+ /* MenuTextColor=White */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"MenuTextColor",
+ L"White");
+
+ /* MenuColor=Blue */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"MenuColor",
+ L"Blue");
+
+ /* TextColor=Yellow */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"TextColor",
+ L"Yellow");
+
+ /* SelectedTextColor=Black */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"SelectedTextColor",
+ L"Black");
+
+ /* SelectedColor=Gray */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"SelectedColor",
+ L"Gray");
+}
+
+
+NTSTATUS
+CreateFreeLoaderIniForDos(PWCHAR IniPath,
+ PWCHAR ArcPath)
+{
+ PINICACHE IniCache;
+ PINICACHESECTION IniSection;
+
+ IniCache = IniCacheCreate();
+
+ CreateCommonFreeLoaderSections(IniCache);
+
+ /* Create "Operating Systems" section */
+ IniSection = IniCacheAppendSection(IniCache,
+ L"Operating Systems");
+
+ /* REACTOS=ReactOS */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"ReactOS",
+ L"\"ReactOS\"");
+
+ /* ReactOS_Debug="ReactOS (Debug)" */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"ReactOS_Debug",
+ L"\"ReactOS (Debug)\"");
+
+ /* DOS=Dos/Windows */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"DOS",
+ L"\"DOS/Windows\"");
+
+ /* Create "ReactOS" section */
+ IniSection = IniCacheAppendSection(IniCache,
+ L"ReactOS");
+
+ /* BootType=ReactOS */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"BootType",
+ L"ReactOS");
+
+ /* SystemPath=<ArcPath> */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"SystemPath",
+ ArcPath);
+
+ /* Create "ReactOS_Debug" section */
+ IniSection = IniCacheAppendSection(IniCache,
+ L"ReactOS_Debug");
+
+ /* BootType=ReactOS */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"BootType",
+ L"ReactOS");
+
+ /* SystemPath=<ArcPath> */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"SystemPath",
+ ArcPath);
+
+ /* Options=/DEBUGPORT=SCREEN */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"Options",
+ L"/DEBUGPORT=SCREEN");
+
+ /* Create "DOS" section */
+ IniSection = IniCacheAppendSection(IniCache,
+ L"DOS");
+
+ /* BootType=BootSector */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"BootType",
+ L"BootSector");
+
+ /* BootDrive=hd0 */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"BootDrive",
+ L"hd0");
+
+ /* BootPartition=1 */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"BootPartition",
+ L"1");
+
+ /* BootSector=BOOTSECT.DOS */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"BootSectorFile",
+ L"BOOTSECT.DOS");
+
+ IniCacheSave(IniCache, IniPath);
+ IniCacheDestroy(IniCache);
+
+ return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS
+CreateFreeLoaderIniForReactos(PWCHAR IniPath,
+ PWCHAR ArcPath)
+{
+ PINICACHE IniCache;
+ PINICACHESECTION IniSection;
+
+ IniCache = IniCacheCreate();
+
+ CreateCommonFreeLoaderSections(IniCache);
+
+ /* Create "Operating Systems" section */
+ IniSection = IniCacheAppendSection(IniCache,
+ L"Operating Systems");
+
+ /* ReactOS="ReactOS" */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"ReactOS",
+ L"\"ReactOS\"");
+
+ /* ReactOS_Debug="ReactOS (Debug)" */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"ReactOS_Debug",
+ L"\"ReactOS (Debug)\"");
+
+ /* Create "ReactOS" section */
+ IniSection = IniCacheAppendSection(IniCache,
+ L"ReactOS");
+
+ /* BootType=ReactOS */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"BootType",
+ L"ReactOS");
+
+ /* SystemPath=<ArcPath> */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"SystemPath",
+ ArcPath);
+
+ /* Create "ReactOS_Debug" section */
+ IniSection = IniCacheAppendSection(IniCache,
+ L"ReactOS_Debug");
+
+ /* BootType=ReactOS */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"BootType",
+ L"ReactOS");
+
+ /* SystemPath=<ArcPath> */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"SystemPath",
+ ArcPath);
+
+ /* Options=/DEBUGPORT=SCREEN */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"Options",
+ L"/DEBUGPORT=SCREEN");
+
+ /* Save the ini file */
+ IniCacheSave(IniCache, IniPath);
+ IniCacheDestroy(IniCache);
+
+ return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS
+UpdateFreeLoaderIni(PWCHAR IniPath,
+ PWCHAR ArcPath)
+{
+ UNICODE_STRING Name;
+ PINICACHE IniCache;
+ PINICACHESECTION IniSection;
+ WCHAR SectionName[80];
+ WCHAR OsName[80];
+ PWCHAR KeyData;
+ ULONG i;
+ NTSTATUS Status;
+
+ RtlInitUnicodeString(&Name,
+ IniPath);
+
+ Status = IniCacheLoad(&IniCache,
+ &Name,
+ FALSE);
+ if (!NT_SUCCESS(Status))
+ return(Status);
+
+ /* Get "Operating Systems" section */
+ IniSection = IniCacheGetSection(IniCache,
+ L"Operating Systems");
+ if (IniSection == NULL)
+ return(STATUS_UNSUCCESSFUL);
+
+ /* Find an unused section name */
+ i = 1;
+ wcscpy(SectionName, L"ReactOS");
+ wcscpy(OsName, L"\"ReactOS\"");
+ while(TRUE)
+ {
+ Status = IniCacheGetKey(IniSection,
+ SectionName,
+ &KeyData);
+ if (!NT_SUCCESS(Status))
+ break;
+
+ swprintf(SectionName, L"ReactOS_%lu", i);
+ swprintf(OsName, L"\"ReactOS %lu\"", i);
+ i++;
+ }
+
+ /* <SectionName>=<OsName> */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ SectionName,
+ OsName);
+
+ /* Create <SectionName> section */
+ IniSection = IniCacheAppendSection(IniCache,
+ SectionName);
+
+ /* BootType=ReactOS */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"BootType",
+ L"ReactOS");
+
+ /* SystemPath=<ArcPath> */
+ IniCacheInsertKey(IniSection,
+ NULL,
+ INSERT_LAST,
+ L"SystemPath",
+ ArcPath);
+
+ IniCacheSave(IniCache, IniPath);
+ IniCacheDestroy(IniCache);
+
+ return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS
+SaveCurrentBootSector(PWSTR RootPath,
+ PWSTR DstPath)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ PUCHAR BootSector;
+
+ /* Allocate buffer for bootsector */
+ BootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ SECTORSIZE);
+ if (BootSector == NULL)
+ return(STATUS_INSUFFICIENT_RESOURCES);
+
+ /* Read current boot sector into buffer */
+ RtlInitUnicodeString(&Name,
+ RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ FILE_READ_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, BootSector);
+ return(Status);
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ BootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, BootSector);
+ return(Status);
+ }
+
+ /* Write bootsector to DstPath */
+ RtlInitUnicodeString(&Name,
+ DstPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&FileHandle,
+ FILE_WRITE_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_SUPERSEDE,
+ FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, BootSector);
+ return(Status);
+ }
+
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ BootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+
+ /* Free the new boot sector */
+ RtlFreeHeap(ProcessHeap, 0, BootSector);
+
+ return(Status);
+}
+
+
+NTSTATUS
+InstallFat16BootCodeToFile(PWSTR SrcPath,
+ PWSTR DstPath,
+ PWSTR RootPath)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ PUCHAR OrigBootSector;
+ PUCHAR NewBootSector;
+
+ /* Allocate buffer for original bootsector */
+ OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ SECTORSIZE);
+ if (OrigBootSector == NULL)
+ return(STATUS_INSUFFICIENT_RESOURCES);
+
+ /* Read current boot sector into buffer */
+ RtlInitUnicodeString(&Name,
+ RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ FILE_READ_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(Status);
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ OrigBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(Status);
+ }
+
+
+ /* Allocate buffer for new bootsector */
+ NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ SECTORSIZE);
+ if (NewBootSector == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ /* Read new bootsector from SrcPath */
+ RtlInitUnicodeString(&Name,
+ SrcPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ FILE_READ_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ /* Adjust bootsector (copy a part of the FAT BPB) */
+ memcpy((NewBootSector + 11), (OrigBootSector + 11), 51 /*fat BPB length*/);
+
+ /* Free the original boot sector */
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+
+ /* Write new bootsector to DstPath */
+ RtlInitUnicodeString(&Name,
+ DstPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&FileHandle,
+ FILE_WRITE_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_OVERWRITE_IF,
+ FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+#if 0
+ FilePosition.QuadPart = 0;
+#endif
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+
+ /* Free the new boot sector */
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+ return(Status);
+}
+
+
+NTSTATUS
+InstallFat32BootCodeToFile(PWSTR SrcPath,
+ PWSTR DstPath,
+ PWSTR RootPath)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ PUCHAR OrigBootSector;
+ PUCHAR NewBootSector;
+ LARGE_INTEGER FileOffset;
+
+ /* Allocate buffer for original bootsector */
+ OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ SECTORSIZE);
+ if (OrigBootSector == NULL)
+ return(STATUS_INSUFFICIENT_RESOURCES);
+
+ /* Read current boot sector into buffer */
+ RtlInitUnicodeString(&Name,
+ RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ FILE_READ_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(Status);
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ OrigBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+CHECKPOINT1;
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(Status);
+ }
+
+ /* Allocate buffer for new bootsector (2 sectors) */
+ NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ 2 * SECTORSIZE);
+ if (NewBootSector == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ /* Read new bootsector from SrcPath */
+ RtlInitUnicodeString(&Name,
+ SrcPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ FILE_READ_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ 2 * SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ /* Adjust bootsector (copy a part of the FAT32 BPB) */
+ memcpy((NewBootSector + 3),
+ (OrigBootSector + 3),
+ 87); /* FAT32 BPB length */
+
+ /* Disable the backup boot sector */
+ NewBootSector[0x32] = 0xFF;
+ NewBootSector[0x33] = 0xFF;
+
+ /* Free the original boot sector */
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+
+ /* Write the first sector of the new bootcode to DstPath */
+ RtlInitUnicodeString(&Name,
+ DstPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&FileHandle,
+ FILE_WRITE_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_SUPERSEDE,
+ FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ /* Write the second sector of the new bootcode to boot disk sector 14 */
+ RtlInitUnicodeString(&Name,
+ RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ FILE_WRITE_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ (NewBootSector + SECTORSIZE),
+ SECTORSIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ }
+ NtClose(FileHandle);
+
+ /* Free the new boot sector */
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+ return(Status);
+}
+
+
+NTSTATUS
+InstallFat16BootCodeToDisk(PWSTR SrcPath,
+ PWSTR RootPath)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ PUCHAR OrigBootSector;
+ PUCHAR NewBootSector;
+
+ /* Allocate buffer for original bootsector */
+ OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ SECTORSIZE);
+ if (OrigBootSector == NULL)
+ return(STATUS_INSUFFICIENT_RESOURCES);
+
+ /* Read current boot sector into buffer */
+ RtlInitUnicodeString(&Name,
+ RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ FILE_READ_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(Status);
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ OrigBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(Status);
+ }
+
+
+ /* Allocate buffer for new bootsector */
+ NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ SECTORSIZE);
+ if (NewBootSector == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ /* Read new bootsector from SrcPath */
+ RtlInitUnicodeString(&Name,
+ SrcPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ FILE_READ_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ /* Adjust bootsector (copy a part of the FAT BPB) */
+ memcpy((NewBootSector + 11), (OrigBootSector + 11), 51 /*fat BPB length*/);
+
+ /* Free the original boot sector */
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+
+ /* Write new bootsector to RootPath */
+ RtlInitUnicodeString(&Name,
+ RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&FileHandle,
+ FILE_WRITE_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_OVERWRITE_IF,
+ FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+#if 0
+ FilePosition.QuadPart = 0;
+#endif
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+
+ /* Free the new boot sector */
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+ return(Status);
+}
+
+
+NTSTATUS
+InstallFat32BootCodeToDisk(PWSTR SrcPath,
+ PWSTR RootPath)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ PUCHAR OrigBootSector;
+ PUCHAR NewBootSector;
+ LARGE_INTEGER FileOffset;
+ USHORT BackupBootSector;
+
+ /* Allocate buffer for original bootsector */
+ OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ SECTORSIZE);
+ if (OrigBootSector == NULL)
+ return(STATUS_INSUFFICIENT_RESOURCES);
+
+ /* Read current boot sector into buffer */
+ RtlInitUnicodeString(&Name,
+ RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ FILE_READ_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(Status);
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ OrigBootSector,
+ SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(Status);
+ }
+
+
+ /* Allocate buffer for new bootsector (2 sectors) */
+ NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ 2 * SECTORSIZE);
+ if (NewBootSector == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ /* Read new bootsector from SrcPath */
+ RtlInitUnicodeString(&Name,
+ SrcPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ FILE_READ_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ 2 * SECTORSIZE,
+ NULL,
+ NULL);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ /* Adjust bootsector (copy a part of the FAT32 BPB) */
+ memcpy((NewBootSector + 3),
+ (OrigBootSector + 3),
+ 87); /* FAT32 BPB length */
+
+ /* Get the location of the backup boot sector */
+ BackupBootSector = (OrigBootSector[0x33] << 8) + OrigBootSector[0x33];
+
+ /* Free the original boot sector */
+ RtlFreeHeap(ProcessHeap, 0, OrigBootSector);
+
+ /* Write the first sector of the new bootcode to DstPath */
+ RtlInitUnicodeString(&Name,
+ RootPath);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ FILE_WRITE_ACCESS | FILE_WRITE_ATTRIBUTES,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ /* Write sector 0 */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+
+ /* Write backup boot sector */
+ if (BackupBootSector != 0xFFFF)
+ {
+ FileOffset.QuadPart = (ULONGLONG)((ULONG)BackupBootSector * SECTORSIZE);
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ NewBootSector,
+ SECTORSIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+ return(Status);
+ }
+ }
+
+ /* Write sector 14 */
+ FileOffset.QuadPart = (ULONGLONG)(14 * SECTORSIZE);
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ (NewBootSector + SECTORSIZE),
+ SECTORSIZE,
+ &FileOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtWriteFile() failed (Status %lx)\n", Status);
+ }
+ NtClose(FileHandle);
+
+ /* Free the new boot sector */
+ RtlFreeHeap(ProcessHeap, 0, NewBootSector);
+
+ return(Status);
+}
+
+
+static NTSTATUS
+UnprotectBootIni(PWSTR FileName,
+ PULONG Attributes)
+{
+ UNICODE_STRING Name;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ FILE_BASIC_INFORMATION FileInfo;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+
+ RtlInitUnicodeString(&Name,
+ FileName);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ if (Status == STATUS_NO_SUCH_FILE)
+ {
+ DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
+ *Attributes = 0;
+ return(STATUS_SUCCESS);
+ }
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
+ return(Status);
+ }
+
+ Status = NtQueryInformationFile(FileHandle,
+ &IoStatusBlock,
+ &FileInfo,
+ sizeof(FILE_BASIC_INFORMATION),
+ FileBasicInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ return(Status);
+ }
+
+ *Attributes = FileInfo.FileAttributes;
+
+ /* Delete attributes SYSTEM, HIDDEN and READONLY */
+ FileInfo.FileAttributes = FileInfo.FileAttributes &
+ ~(FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
+
+ Status = NtSetInformationFile(FileHandle,
+ &IoStatusBlock,
+ &FileInfo,
+ sizeof(FILE_BASIC_INFORMATION),
+ FileBasicInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
+ }
+
+ NtClose(FileHandle);
+ return(Status);
+}
+
+
+static NTSTATUS
+ProtectBootIni(PWSTR FileName,
+ ULONG Attributes)
+{
+ UNICODE_STRING Name;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ FILE_BASIC_INFORMATION FileInfo;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+
+ RtlInitUnicodeString(&Name,
+ FileName);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
+ return(Status);
+ }
+
+ Status = NtQueryInformationFile(FileHandle,
+ &IoStatusBlock,
+ &FileInfo,
+ sizeof(FILE_BASIC_INFORMATION),
+ FileBasicInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtQueryInformationFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ return(Status);
+ }
+
+ FileInfo.FileAttributes = FileInfo.FileAttributes | Attributes;
+
+ Status = NtSetInformationFile(FileHandle,
+ &IoStatusBlock,
+ &FileInfo,
+ sizeof(FILE_BASIC_INFORMATION),
+ FileBasicInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtSetInformationFile() failed (Status %lx)\n", Status);
+ }
+
+ NtClose(FileHandle);
+ return(Status);
+}
+
+
+NTSTATUS
+UpdateBootIni(PWSTR BootIniPath,
+ PWSTR EntryName,
+ PWSTR EntryValue)
+{
+ UNICODE_STRING Name;
+ PINICACHE Cache = NULL;
+ PINICACHESECTION Section = NULL;
+ NTSTATUS Status;
+ ULONG FileAttribute;
+
+ RtlInitUnicodeString(&Name,
+ BootIniPath);
+
+ Status = IniCacheLoad(&Cache,
+ &Name,
+ FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+CHECKPOINT1;
+ return(Status);
+ }
+
+ Section = IniCacheGetSection(Cache,
+ L"operating systems");
+ if (Section == NULL)
+ {
+CHECKPOINT1;
+ IniCacheDestroy(Cache);
+ return(STATUS_UNSUCCESSFUL);
+ }
+
+ IniCacheInsertKey(Section,
+ NULL,
+ INSERT_LAST,
+ EntryName,
+ EntryValue);
+
+ Status = UnprotectBootIni(BootIniPath,
+ &FileAttribute);
+ if (!NT_SUCCESS(Status))
+ {
+CHECKPOINT1;
+ IniCacheDestroy(Cache);
+ return(Status);
+ }
+
+ Status = IniCacheSave(Cache,
+ BootIniPath);
+ if (!NT_SUCCESS(Status))
+ {
+CHECKPOINT1;
+ IniCacheDestroy(Cache);
+ return(Status);
+ }
+
+ FileAttribute |= (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
+ Status = ProtectBootIni(BootIniPath,
+ FileAttribute);
+
+ IniCacheDestroy(Cache);
+
+ return(Status);
+}
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2002 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS text-mode setup
+ * FILE: subsys/system/usetup/bootsup.h
+ * PURPOSE: Bootloader support functions
+ * PROGRAMMER: Eric Kohl
+ */
+
+#ifndef __BOOTSUP_H__
+#define __BOOTSUP_H__
+
+NTSTATUS
+CreateFreeLoaderIniForDos(PWCHAR IniPath,
+ PWCHAR ArcPath);
+
+NTSTATUS
+CreateFreeLoaderIniForReactos(PWCHAR IniPath,
+ PWCHAR ArcPath);
+
+NTSTATUS
+UpdateFreeLoaderIni(PWCHAR IniPath,
+ PWCHAR ArcPath);
+
+NTSTATUS
+SaveCurrentBootSector(PWSTR RootPath,
+ PWSTR DstPath);
+
+NTSTATUS
+InstallFat16BootCodeToFile(PWSTR SrcPath,
+ PWSTR DstPath,
+ PWSTR RootPath);
+
+NTSTATUS
+InstallFat32BootCodeToFile(PWSTR SrcPath,
+ PWSTR DstPath,
+ PWSTR RootPath);
+
+NTSTATUS
+InstallFat16BootCodeToDisk(PWSTR SrcPath,
+ PWSTR RootPath);
+
+NTSTATUS
+InstallFat32BootCodeToDisk(PWSTR SrcPath,
+ PWSTR RootPath);
+
+
+NTSTATUS
+UpdateBootIni(PWSTR BootIniPath,
+ PWSTR EntryName,
+ PWSTR EntryValue);
+
+#endif /* __BOOTSUP_H__ */
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2002 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS text-mode setup
+ * FILE: subsys/system/usetup/filequeue.c
+ * PURPOSE: File queue functions
+ * PROGRAMMER: Eric Kohl
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <ntdll/rtl.h>
+
+#include "usetup.h"
+#include "filesup.h"
+#include "filequeue.h"
+
+
+/* INCLUDES *****************************************************************/
+
+
+typedef struct _QUEUEENTRY
+{
+ struct _QUEUEENTRY *Prev;
+ struct _QUEUEENTRY *Next;
+
+ PWSTR SourceRootPath;
+ PWSTR SourcePath;
+ PWSTR SourceFilename;
+ PWSTR TargetDirectory;
+ PWSTR TargetFilename;
+
+} QUEUEENTRY, *PQUEUEENTRY;
+
+
+typedef struct _FILEQUEUEHEADER
+{
+ PQUEUEENTRY CopyHead;
+ PQUEUEENTRY CopyTail;
+ ULONG CopyCount;
+} FILEQUEUEHEADER, *PFILEQUEUEHEADER;
+
+
+/* FUNCTIONS ****************************************************************/
+
+HSPFILEQ
+SetupOpenFileQueue(VOID)
+{
+ PFILEQUEUEHEADER QueueHeader;
+
+ /* Allocate queue header */
+ QueueHeader = (PFILEQUEUEHEADER)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(FILEQUEUEHEADER));
+ if (QueueHeader == NULL)
+ return(NULL);
+
+ /* Initialize queue header */
+ RtlZeroMemory(QueueHeader,
+ sizeof(FILEQUEUEHEADER));
+
+
+ return((HSPFILEQ)QueueHeader);
+}
+
+
+BOOL
+SetupCloseFileQueue(HSPFILEQ QueueHandle)
+{
+ PFILEQUEUEHEADER QueueHeader;
+ PQUEUEENTRY Entry;
+
+ if (QueueHandle == NULL)
+ return(FALSE);
+
+ QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
+
+ /* Delete copy queue */
+ Entry = QueueHeader->CopyHead;
+ while (Entry != NULL)
+ {
+ /* Delete all strings */
+ if (Entry->SourceRootPath != NULL)
+ RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
+ if (Entry->SourcePath != NULL)
+ RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
+ if (Entry->SourceFilename != NULL)
+ RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename);
+ if (Entry->TargetDirectory != NULL)
+ RtlFreeHeap(ProcessHeap, 0, Entry->TargetDirectory);
+ if (Entry->TargetFilename != NULL)
+ RtlFreeHeap(ProcessHeap, 0, Entry->TargetFilename);
+
+ /* Unlink current queue entry */
+ if (Entry->Next != NULL)
+ {
+ QueueHeader->CopyHead = Entry->Next;
+ QueueHeader->CopyHead->Prev = NULL;
+ }
+ else
+ {
+ QueueHeader->CopyHead = NULL;
+ QueueHeader->CopyTail = NULL;
+ }
+
+ /* Delete queue entry */
+ RtlFreeHeap(ProcessHeap, 0, Entry);
+
+ /* Get next queue entry */
+ Entry = QueueHeader->CopyHead;
+ }
+
+ /* Delete queue header */
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ QueueHeader);
+
+ return(TRUE);
+}
+
+
+BOOL
+SetupQueueCopy(HSPFILEQ QueueHandle,
+ PCWSTR SourceRootPath,
+ PCWSTR SourcePath,
+ PCWSTR SourceFilename,
+ PCWSTR TargetDirectory,
+ PCWSTR TargetFilename)
+{
+ PFILEQUEUEHEADER QueueHeader;
+ PQUEUEENTRY Entry;
+ ULONG Length;
+
+ if (QueueHandle == NULL ||
+ SourceRootPath == NULL ||
+ SourceFilename == NULL ||
+ TargetDirectory == NULL)
+ return(FALSE);
+
+ QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
+
+ /* Allocate new queue entry */
+ Entry = (PQUEUEENTRY)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(QUEUEENTRY));
+ if (Entry == NULL)
+ return(FALSE);
+
+ RtlZeroMemory(Entry,
+ sizeof(QUEUEENTRY));
+
+ /* Copy source root path */
+ Length = wcslen(SourceRootPath);
+ Entry->SourceRootPath = RtlAllocateHeap(ProcessHeap,
+ 0,
+ (Length + 1) * sizeof(WCHAR));
+ if (Entry->SourceRootPath == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, Entry);
+ return(FALSE);
+ }
+ wcsncpy(Entry->SourceRootPath, SourceRootPath, Length);
+ Entry->SourceRootPath[Length] = (WCHAR)0;
+
+ /* Copy source path */
+ if (SourcePath != NULL)
+ {
+ Length = wcslen(SourcePath);
+ Entry->SourcePath = RtlAllocateHeap(ProcessHeap,
+ 0,
+ (Length + 1) * sizeof(WCHAR));
+ if (Entry->SourcePath == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
+ RtlFreeHeap(ProcessHeap, 0, Entry);
+ return(FALSE);
+ }
+ wcsncpy(Entry->SourcePath, SourcePath, Length);
+ Entry->SourcePath[Length] = (WCHAR)0;
+ }
+
+ /* Copy source file name */
+ Length = wcslen(SourceFilename);
+ Entry->SourceFilename = RtlAllocateHeap(ProcessHeap,
+ 0,
+ (Length + 1) * sizeof(WCHAR));
+ if (Entry->SourceFilename == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
+ RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
+ RtlFreeHeap(ProcessHeap, 0, Entry);
+ return(FALSE);
+ }
+ wcsncpy(Entry->SourceFilename, SourceFilename, Length);
+ Entry->SourceFilename[Length] = (WCHAR)0;
+
+ /* Copy target directory */
+ Length = wcslen(TargetDirectory);
+ if (TargetDirectory[Length] == '\\')
+ Length--;
+ Entry->TargetDirectory = RtlAllocateHeap(ProcessHeap,
+ 0,
+ (Length + 1) * sizeof(WCHAR));
+ if (Entry->TargetDirectory == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
+ RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
+ RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename);
+ RtlFreeHeap(ProcessHeap, 0, Entry);
+ return(FALSE);
+ }
+ wcsncpy(Entry->TargetDirectory, TargetDirectory, Length);
+ Entry->TargetDirectory[Length] = (WCHAR)0;
+
+ /* Copy optional target filename */
+ if (TargetFilename != NULL)
+ {
+ Length = wcslen(TargetFilename);
+ Entry->TargetFilename = RtlAllocateHeap(ProcessHeap,
+ 0,
+ (Length + 1) * sizeof(WCHAR));
+ if (Entry->TargetFilename == NULL)
+ {
+ RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
+ RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
+ RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename);
+ RtlFreeHeap(ProcessHeap, 0, Entry->TargetDirectory);
+ RtlFreeHeap(ProcessHeap, 0, Entry);
+ return(FALSE);
+ }
+ wcsncpy(Entry->TargetFilename, TargetFilename, Length);
+ Entry->TargetFilename[Length] = (WCHAR)0;
+ }
+
+ /* Append queue entry */
+ if (QueueHeader->CopyHead == NULL) // && QueueHeader->CopyTail == NULL)
+ {
+ Entry->Prev = NULL;
+ Entry->Next = NULL;
+ QueueHeader->CopyHead = Entry;
+ QueueHeader->CopyTail = Entry;
+ }
+ else
+ {
+ Entry->Prev = QueueHeader->CopyTail;
+ Entry->Next = NULL;
+ QueueHeader->CopyTail->Next = Entry;
+ QueueHeader->CopyTail = Entry;
+ }
+ QueueHeader->CopyCount++;
+
+ return(TRUE);
+}
+
+
+BOOL
+SetupCommitFileQueue(HSPFILEQ QueueHandle,
+ PCWSTR TargetRootPath,
+ PCWSTR TargetPath,
+ PSP_FILE_CALLBACK MsgHandler,
+ PVOID Context)
+{
+ PFILEQUEUEHEADER QueueHeader;
+ PQUEUEENTRY Entry;
+ NTSTATUS Status;
+
+ WCHAR FileSrcPath[MAX_PATH];
+ WCHAR FileDstPath[MAX_PATH];
+
+ if (QueueHandle == NULL)
+ return(FALSE);
+
+ QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
+
+ MsgHandler(Context,
+ SPFILENOTIFY_STARTQUEUE,
+ NULL,
+ NULL);
+
+ MsgHandler(Context,
+ SPFILENOTIFY_STARTSUBQUEUE,
+ (PVOID)FILEOP_COPY,
+ (PVOID)QueueHeader->CopyCount);
+
+ /* Commit copy queue */
+ Entry = QueueHeader->CopyHead;
+ while (Entry != NULL)
+ {
+ /* Build the full source path */
+ wcscpy(FileSrcPath, Entry->SourceRootPath);
+ if (Entry->SourcePath != NULL)
+ wcscat(FileSrcPath, Entry->SourcePath);
+ wcscat(FileSrcPath, L"\\");
+ wcscat(FileSrcPath, Entry->SourceFilename);
+
+ /* Build the full target path */
+ wcscpy(FileDstPath, TargetRootPath);
+ if (Entry->TargetDirectory[0] == L'\\')
+ {
+ wcscat(FileDstPath, Entry->TargetDirectory);
+ }
+ else
+ {
+ if (TargetPath != NULL)
+ {
+ if (TargetPath[0] != L'\\')
+ wcscat(FileDstPath, L"\\");
+ wcscat(FileDstPath, TargetPath);
+ }
+ wcscat(FileDstPath, L"\\");
+ wcscat(FileDstPath, Entry->TargetDirectory);
+ }
+ wcscat(FileDstPath, L"\\");
+ if (Entry->TargetFilename != NULL)
+ wcscat(FileDstPath, Entry->TargetFilename);
+ else
+ wcscat(FileDstPath, Entry->SourceFilename);
+
+ /* FIXME: Do it! */
+ DPRINT("'%S' ==> '%S'\n",
+ FileSrcPath,
+ FileDstPath);
+
+ MsgHandler(Context,
+ SPFILENOTIFY_STARTCOPY,
+ (PVOID)Entry->SourceFilename,
+ (PVOID)FILEOP_COPY);
+
+ /* Copy the file */
+ Status = SetupCopyFile(FileSrcPath, FileDstPath);
+ if (!NT_SUCCESS(Status))
+ {
+ MsgHandler(Context,
+ SPFILENOTIFY_COPYERROR,
+ (PVOID)Entry->SourceFilename,
+ (PVOID)FILEOP_COPY);
+
+ }
+ else
+ {
+ MsgHandler(Context,
+ SPFILENOTIFY_ENDCOPY,
+ (PVOID)Entry->SourceFilename,
+ (PVOID)FILEOP_COPY);
+ }
+
+ Entry = Entry->Next;
+ }
+
+ MsgHandler(Context,
+ SPFILENOTIFY_ENDSUBQUEUE,
+ (PVOID)FILEOP_COPY,
+ NULL);
+
+ MsgHandler(Context,
+ SPFILENOTIFY_ENDQUEUE,
+ NULL,
+ NULL);
+
+ return(TRUE);
+}
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2002 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS text-mode setup
+ * FILE: subsys/system/usetup/filequeue.h
+ * PURPOSE: File queue functions
+ * PROGRAMMER: Eric Kohl
+ */
+
+#ifndef __FILEQUEUE_H__
+#define __FILEQUEUE_H__
+
+
+#define SPFILENOTIFY_STARTQUEUE 0x1
+#define SPFILENOTIFY_ENDQUEUE 0x2
+#define SPFILENOTIFY_STARTSUBQUEUE 0x3
+#define SPFILENOTIFY_ENDSUBQUEUE 0x4
+
+#define SPFILENOTIFY_STARTCOPY 0xb
+#define SPFILENOTIFY_ENDCOPY 0xc
+#define SPFILENOTIFY_COPYERROR 0xd
+
+#define FILEOP_COPY 0x0
+#define FILEOP_RENAME 0x1
+#define FILEOP_DELETE 0x2
+#define FILEOP_BACKUP 0x3
+
+#define FILEOP_ABORT 0x0
+#define FILEOP_DOIT 0x1
+#define FILEOP_SKIP 0x2
+#define FILEOP_RETRY FILEOP_DOIT
+#define FILEOP_NEWPATH 0x4
+
+
+/* TYPES ********************************************************************/
+
+typedef PVOID HSPFILEQ;
+
+typedef ULONG (*PSP_FILE_CALLBACK)(PVOID Context,
+ ULONG Notification,
+ PVOID Param1,
+ PVOID Param2);
+
+
+/* FUNCTIONS ****************************************************************/
+
+HSPFILEQ
+SetupOpenFileQueue(VOID);
+
+BOOL
+SetupCloseFileQueue(HSPFILEQ QueueHandle);
+
+BOOL
+SetupQueueCopy(HSPFILEQ QueueHandle,
+ PCWSTR SourceRootPath,
+ PCWSTR SourcePath,
+ PCWSTR SourceFilename,
+ PCWSTR TargetDirectory,
+ PCWSTR TargetFilename);
+
+BOOL
+SetupCommitFileQueue(HSPFILEQ QueueHandle,
+ PCWSTR TargetRootPath,
+ PCWSTR TargetPath,
+ PSP_FILE_CALLBACK MsgHandler,
+ PVOID Context);
+
+#endif /* __FILEQUEUE_H__ */
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2002 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS text-mode setup
+ * FILE: subsys/system/usetup/filesup.c
+ * PURPOSE: File support functions
+ * PROGRAMMER: Eric Kohl
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <ntdll/rtl.h>
+
+#include "usetup.h"
+#include "filesup.h"
+
+
+/* FUNCTIONS ****************************************************************/
+
+
+NTSTATUS
+CreateDirectory(PWCHAR DirectoryName)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING PathName;
+ HANDLE DirectoryHandle;
+ NTSTATUS Status;
+
+ RtlCreateUnicodeString(&PathName,
+ DirectoryName);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &PathName,
+ OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&DirectoryHandle,
+ DIRECTORY_ALL_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_DIRECTORY,
+ 0,
+ FILE_CREATE,
+ FILE_DIRECTORY_FILE,
+ NULL,
+ 0);
+ if (NT_SUCCESS(Status))
+ {
+ NtClose(DirectoryHandle);
+ }
+
+ RtlFreeUnicodeString(&PathName);
+
+ return(Status);
+}
+
+
+NTSTATUS
+SetupCopyFile(PWCHAR SourceFileName,
+ PWCHAR DestinationFileName)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE FileHandleSource;
+ HANDLE FileHandleDest;
+ IO_STATUS_BLOCK IoStatusBlock;
+ FILE_STANDARD_INFORMATION FileStandard;
+ FILE_BASIC_INFORMATION FileBasic;
+ FILE_POSITION_INFORMATION FilePosition;
+ PUCHAR Buffer;
+ ULONG RegionSize;
+ UNICODE_STRING FileName;
+ NTSTATUS Status;
+
+ Buffer = NULL;
+
+ RtlInitUnicodeString(&FileName,
+ SourceFileName);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &FileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandleSource,
+ FILE_READ_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ,
+ FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY);
+ if (!NT_SUCCESS(Status))
+ {
+CHECKPOINT1;
+ return(Status);
+ }
+
+ Status = NtQueryInformationFile(FileHandleSource,
+ &IoStatusBlock,
+ &FileStandard,
+ sizeof(FILE_STANDARD_INFORMATION),
+ FileStandardInformation);
+ if (!NT_SUCCESS(Status))
+ {
+CHECKPOINT1;
+ NtClose(FileHandleSource);
+ return(Status);
+ }
+
+ Status = NtQueryInformationFile(FileHandleSource,
+ &IoStatusBlock,&FileBasic,
+ sizeof(FILE_BASIC_INFORMATION),
+ FileBasicInformation);
+ if (!NT_SUCCESS(Status))
+ {
+CHECKPOINT1;
+ NtClose(FileHandleSource);
+ return(Status);
+ }
+
+ RtlInitUnicodeString(&FileName,
+ DestinationFileName);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &FileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&FileHandleDest,
+ FILE_WRITE_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_OVERWRITE_IF,
+ FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+CHECKPOINT1;
+ NtClose(FileHandleSource);
+ return(Status);
+ }
+
+ FilePosition.CurrentByteOffset.QuadPart = 0;
+
+ Status = NtSetInformationFile(FileHandleSource,
+ &IoStatusBlock,
+ &FilePosition,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
+ if (!NT_SUCCESS(Status))
+ {
+CHECKPOINT1;
+ NtClose(FileHandleSource);
+ NtClose(FileHandleDest);
+ return(Status);
+ }
+
+ Status = NtSetInformationFile(FileHandleDest,
+ &IoStatusBlock,
+ &FilePosition,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
+ if (!NT_SUCCESS(Status))
+ {
+CHECKPOINT1;
+ NtClose(FileHandleSource);
+ NtClose(FileHandleDest);
+ return(Status);
+ }
+
+ RegionSize = PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart);
+ if (RegionSize > 0x100000)
+ {
+ RegionSize = 0x100000;
+ }
+ Status = NtAllocateVirtualMemory(NtCurrentProcess(),
+ (PVOID *)&Buffer,
+ 2,
+ &RegionSize,
+ MEM_RESERVE | MEM_COMMIT,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status))
+ {
+CHECKPOINT1;
+ NtClose(FileHandleSource);
+ NtClose(FileHandleDest);
+ return(Status);
+ }
+
+ while (TRUE)
+ {
+ Status = NtReadFile(FileHandleSource,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ Buffer,
+ RegionSize,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ NtFreeVirtualMemory(NtCurrentProcess(),
+ (PVOID *)&Buffer,
+ &RegionSize,
+ MEM_RELEASE);
+ if (Status == STATUS_END_OF_FILE)
+ {
+ DPRINT("STATUS_END_OF_FILE\n");
+ break;
+ }
+CHECKPOINT1;
+ NtClose(FileHandleSource);
+ NtClose(FileHandleDest);
+ return(Status);
+ }
+
+ DPRINT("Bytes read %lu\n", IoStatusBlock.Information);
+
+ Status = NtWriteFile(FileHandleDest,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ Buffer,
+ IoStatusBlock.Information,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+CHECKPOINT1;
+ NtFreeVirtualMemory(NtCurrentProcess(),
+ (PVOID *)&Buffer,
+ &RegionSize,
+ MEM_RELEASE);
+ NtClose(FileHandleSource);
+ NtClose(FileHandleDest);
+ return(Status);
+ }
+ }
+
+
+ /* Copy file date/time from source file */
+ Status = NtSetInformationFile(FileHandleDest,
+ &IoStatusBlock,
+ &FileBasic,
+ sizeof(FILE_BASIC_INFORMATION),
+ FileBasicInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status);
+ }
+
+ NtClose(FileHandleSource);
+ NtClose(FileHandleDest);
+
+ return(Status);
+}
+
+
+BOOLEAN
+DoesFileExist(PWSTR PathName,
+ PWSTR FileName)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING Name;
+ WCHAR FullName[MAX_PATH];
+ HANDLE FileHandle;
+ NTSTATUS Status;
+
+ wcscpy(FullName, PathName);
+ if (FileName != NULL)
+ {
+ if (FileName[0] != L'\\')
+ wcscat(FullName, L"\\");
+ wcscat(FullName, FileName);
+ }
+
+ RtlInitUnicodeString(&Name,
+ FullName);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ FILE_READ_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ 0,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ if (!NT_SUCCESS(Status))
+ {
+CHECKPOINT1;
+ return(FALSE);
+ }
+
+ NtClose(FileHandle);
+
+ return(TRUE);
+}
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2002 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS text-mode setup
+ * FILE: subsys/system/usetup/filesup.h
+ * PURPOSE: File support functions
+ * PROGRAMMER: Eric Kohl
+ */
+
+#ifndef __FILESUP_H__
+#define __FILESUP_H__
+
+NTSTATUS
+CreateDirectory(PWCHAR DirectoryName);
+
+NTSTATUS
+SetupCopyFile(PWCHAR SourceFileName,
+ PWCHAR DestinationFileName);
+
+BOOLEAN
+DoesFileExist(PWSTR PathName,
+ PWSTR FileName);
+
+
+#endif /* __FILESUP_H__ */
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2002 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS text-mode setup
+ * FILE: subsys/system/usetup/inicache.c
+ * PURPOSE: INI file parser that caches contents of INI file in memory
+ * PROGRAMMER: Royce Mitchell III
+ * Eric Kohl
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include "usetup.h"
+#include "inicache.h"
+
+
+/* PRIVATE FUNCTIONS ********************************************************/
+
+static PINICACHEKEY
+IniCacheFreeKey(PINICACHEKEY Key)
+{
+ PINICACHEKEY Next;
+
+ if (Key == NULL)
+ {
+ return(NULL);
+ }
+
+ Next = Key->Next;
+ if (Key->Name != NULL)
+ {
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Key->Name);
+ Key->Name = NULL;
+ }
+
+ if (Key->Data != NULL)
+ {
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Key->Data);
+ Key->Data = NULL;
+ }
+
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Key);
+
+ return(Next);
+}
+
+
+static PINICACHESECTION
+IniCacheFreeSection(PINICACHESECTION Section)
+{
+ PINICACHESECTION Next;
+
+ if (Section == NULL)
+ {
+ return(NULL);
+ }
+
+ Next = Section->Next;
+ while (Section->FirstKey != NULL)
+ {
+ Section->FirstKey = IniCacheFreeKey(Section->FirstKey);
+ }
+ Section->LastKey = NULL;
+
+ if (Section->Name != NULL)
+ {
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Section->Name);
+ Section->Name = NULL;
+ }
+
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Section);
+
+ return(Next);
+}
+
+
+static PINICACHEKEY
+IniCacheFindKey(PINICACHESECTION Section,
+ PWCHAR Name,
+ ULONG NameLength)
+{
+ PINICACHEKEY Key;
+
+ Key = Section->FirstKey;
+ while (Key != NULL)
+ {
+ if (NameLength == wcslen(Key->Name))
+ {
+ if (_wcsnicmp(Key->Name, Name, NameLength) == 0)
+ break;
+ }
+
+ Key = Key->Next;
+ }
+
+ return(Key);
+}
+
+
+static PINICACHEKEY
+IniCacheAddKey(PINICACHESECTION Section,
+ PCHAR Name,
+ ULONG NameLength,
+ PCHAR Data,
+ ULONG DataLength)
+{
+ PINICACHEKEY Key;
+ ULONG i;
+
+ Key = NULL;
+
+ if (Section == NULL ||
+ Name == NULL ||
+ NameLength == 0 ||
+ Data == NULL ||
+ DataLength == 0)
+ {
+ DPRINT("Invalid parameter\n");
+ return(NULL);
+ }
+
+ Key = (PINICACHEKEY)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(INICACHEKEY));
+ if (Key == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ return(NULL);
+ }
+
+ RtlZeroMemory(Key,
+ sizeof(INICACHEKEY));
+
+
+ Key->Name = RtlAllocateHeap(ProcessHeap,
+ 0,
+ (NameLength + 1) * sizeof(WCHAR));
+ if (Key->Name == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Key);
+ return(NULL);
+ }
+
+ /* Copy value name */
+ for (i = 0; i < NameLength; i++)
+ {
+ Key->Name[i] = (WCHAR)Name[i];
+ }
+ Key->Name[NameLength] = 0;
+
+
+ Key->Data = RtlAllocateHeap(ProcessHeap,
+ 0,
+ (DataLength + 1) * sizeof(WCHAR));
+ if (Key->Data == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Key->Name);
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Key);
+ return(NULL);
+ }
+
+ /* Copy value data */
+ for (i = 0; i < DataLength; i++)
+ {
+ Key->Data[i] = (WCHAR)Data[i];
+ }
+ Key->Data[DataLength] = 0;
+
+
+ if (Section->FirstKey == NULL)
+ {
+ Section->FirstKey = Key;
+ Section->LastKey = Key;
+ }
+ else
+ {
+ Section->LastKey->Next = Key;
+ Key->Prev = Section->LastKey;
+ Section->LastKey = Key;
+ }
+
+ return(Key);
+}
+
+
+static PINICACHESECTION
+IniCacheFindSection(PINICACHE Cache,
+ PWCHAR Name,
+ ULONG NameLength)
+{
+ PINICACHESECTION Section = NULL;
+
+ if (Cache == NULL || Name == NULL || NameLength == 0)
+ {
+ return(NULL);
+ }
+
+ Section = Cache->FirstSection;
+
+ /* iterate through list of sections */
+ while (Section != NULL)
+ {
+ if (NameLength == wcslen(Section->Name))
+ {
+ /* are the contents the same too? */
+ if (_wcsnicmp(Section->Name, Name, NameLength) == 0)
+ break;
+ }
+
+ /* get the next section*/
+ Section = Section->Next;
+ }
+
+ return(Section);
+}
+
+
+static PINICACHESECTION
+IniCacheAddSection(PINICACHE Cache,
+ PCHAR Name,
+ ULONG NameLength)
+{
+ PINICACHESECTION Section = NULL;
+ ULONG i;
+
+ if (Cache == NULL || Name == NULL || NameLength == 0)
+ {
+ DPRINT("Invalid parameter\n");
+ return(NULL);
+ }
+
+ Section = (PINICACHESECTION)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(INICACHESECTION));
+ if (Section == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ return(NULL);
+ }
+ RtlZeroMemory(Section,
+ sizeof(INICACHESECTION));
+
+ /* Allocate and initialize section name */
+ Section->Name = RtlAllocateHeap(ProcessHeap,
+ 0,
+ (NameLength + 1) * sizeof(WCHAR));
+ if (Section->Name == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Section);
+ return(NULL);
+ }
+
+ /* Copy section name */
+ for (i = 0; i < NameLength; i++)
+ {
+ Section->Name[i] = (WCHAR)Name[i];
+ }
+ Section->Name[NameLength] = 0;
+
+ /* Append section */
+ if (Cache->FirstSection == NULL)
+ {
+ Cache->FirstSection = Section;
+ Cache->LastSection = Section;
+ }
+ else
+ {
+ Cache->LastSection->Next = Section;
+ Section->Prev = Cache->LastSection;
+ Cache->LastSection = Section;
+ }
+
+ return(Section);
+}
+
+
+static PCHAR
+IniCacheSkipWhitespace(PCHAR Ptr)
+{
+ while (*Ptr != 0 && isspace(*Ptr))
+ Ptr++;
+
+ return((*Ptr == 0) ? NULL : Ptr);
+}
+
+
+static PCHAR
+IniCacheSkipToNextSection(PCHAR Ptr)
+{
+ while (*Ptr != 0 && *Ptr != '[')
+ {
+ while (*Ptr != 0 && *Ptr != L'\n')
+ {
+ Ptr++;
+ }
+ Ptr++;
+ }
+
+ return((*Ptr == 0) ? NULL : Ptr);
+}
+
+
+static PCHAR
+IniCacheGetSectionName(PCHAR Ptr,
+ PCHAR *NamePtr,
+ PULONG NameSize)
+{
+ ULONG Size = 0;
+ CHAR Name[256];
+
+ *NamePtr = NULL;
+ *NameSize = 0;
+
+ /* skip whitespace */
+ while (*Ptr != 0 && isspace(*Ptr))
+ {
+ Ptr++;
+ }
+
+ *NamePtr = Ptr;
+
+ while (*Ptr != 0 && *Ptr != ']')
+ {
+ Size++;
+ Ptr++;
+ }
+
+ Ptr++;
+
+ while (*Ptr != 0 && *Ptr != L'\n')
+ {
+ Ptr++;
+ }
+ Ptr++;
+
+ *NameSize = Size;
+
+ strncpy(Name, *NamePtr, Size);
+ Name[Size] = 0;
+
+ DPRINT("SectionName: '%s'\n", Name);
+
+ return(Ptr);
+}
+
+
+static PCHAR
+IniCacheGetKeyName(PCHAR Ptr,
+ PCHAR *NamePtr,
+ PULONG NameSize)
+{
+ ULONG Size = 0;
+
+ *NamePtr = NULL;
+ *NameSize = 0;
+
+ while(Ptr && *Ptr)
+ {
+ *NamePtr = NULL;
+ *NameSize = 0;
+ Size = 0;
+
+ /* skip whitespace and empty lines */
+ while (isspace(*Ptr) || *Ptr == '\n' || *Ptr == '\r')
+ {
+ Ptr++;
+ }
+ if (*Ptr == 0)
+ {
+ continue;
+ }
+
+ *NamePtr = Ptr;
+
+ while (*Ptr != 0 && !isspace(*Ptr) && *Ptr != '=' && *Ptr != ';')
+ {
+ Size++;
+ Ptr++;
+ }
+ if (*Ptr == ';')
+ {
+ while (*Ptr != 0 && *Ptr != '\r' && *Ptr != '\n')
+ {
+ Ptr++;
+ }
+ }
+ else
+ {
+ *NameSize = Size;
+ break;
+ }
+ }
+
+ return(Ptr);
+}
+
+
+static PCHAR
+IniCacheGetKeyValue(PCHAR Ptr,
+ PCHAR *DataPtr,
+ PULONG DataSize,
+ BOOL String)
+{
+ ULONG Size = 0;
+
+ *DataPtr = NULL;
+ *DataSize = 0;
+
+ /* Skip whitespace */
+ while (*Ptr != 0 && isspace(*Ptr))
+ {
+ Ptr++;
+ }
+
+ /* Check and skip '=' */
+ if (*Ptr != '=')
+ {
+ return(NULL);
+ }
+ Ptr++;
+
+ /* Skip whitespace */
+ while (*Ptr != 0 && isspace(*Ptr))
+ {
+ Ptr++;
+ }
+
+ if (*Ptr == '"' && String)
+ {
+ Ptr++;
+
+ /* Get data */
+ *DataPtr = Ptr;
+ while (*Ptr != '"')
+ {
+ Ptr++;
+ Size++;
+ }
+ Ptr++;
+ while (*Ptr && *Ptr != '\r' && *Ptr != '\n')
+ {
+ Ptr++;
+ }
+ }
+ else
+ {
+ /* Get data */
+ *DataPtr = Ptr;
+ while (*Ptr != 0 && *Ptr != '\r' && *Ptr != ';')
+ {
+ Ptr++;
+ Size++;
+ }
+ }
+
+ /* Skip to next line */
+ if (*Ptr == '\r')
+ Ptr++;
+ if (*Ptr == '\n')
+ Ptr++;
+
+ *DataSize = Size;
+
+ return(Ptr);
+}
+
+
+
+
+/* PUBLIC FUNCTIONS *********************************************************/
+
+NTSTATUS
+IniCacheLoad(PINICACHE *Cache,
+ PUNICODE_STRING FileName,
+ BOOL String)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ FILE_STANDARD_INFORMATION FileInfo;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE FileHandle;
+ NTSTATUS Status;
+ PCHAR FileBuffer;
+ ULONG FileLength;
+ PCHAR Ptr;
+ LARGE_INTEGER FileOffset;
+
+ ULONG i;
+ PINICACHESECTION Section;
+ PINICACHEKEY Key;
+
+ PCHAR SectionName;
+ ULONG SectionNameSize;
+
+ PCHAR KeyName;
+ ULONG KeyNameSize;
+
+ PCHAR KeyValue;
+ ULONG KeyValueSize;
+
+ *Cache = NULL;
+
+ /* Open ini file */
+ InitializeObjectAttributes(&ObjectAttributes,
+ FileName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandle,
+ GENERIC_READ | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ,
+ FILE_NON_DIRECTORY_FILE);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtOpenFile() failed (Status %lx)\n", Status);
+ return(Status);
+ }
+
+ DPRINT("NtOpenFile() successful\n");
+
+ /* Query file size */
+ Status = NtQueryInformationFile(FileHandle,
+ &IoStatusBlock,
+ &FileInfo,
+ sizeof(FILE_STANDARD_INFORMATION),
+ FileStandardInformation);
+ if (Status == STATUS_PENDING)
+ {
+ DPRINT("NtQueryInformationFile() returns STATUS_PENDING\n");
+
+ }
+ else if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ return(Status);
+ }
+
+ FileLength = FileInfo.EndOfFile.u.LowPart;
+
+ DPRINT("File size: %lu\n", FileLength);
+
+ /* Allocate file buffer */
+ FileBuffer = RtlAllocateHeap(ProcessHeap,
+ 0,
+ FileLength + 1);
+ if (FileBuffer == NULL)
+ {
+ DPRINT1("RtlAllocateHeap() failed\n");
+ NtClose(FileHandle);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ /* Read file */
+ FileOffset.QuadPart = 0ULL;
+ Status = NtReadFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FileBuffer,
+ FileLength,
+ &FileOffset,
+ NULL);
+
+ if (Status == STATUS_PENDING)
+ {
+ DPRINT("NtReadFile() returns STATUS_PENDING\n");
+
+ Status = IoStatusBlock.Status;
+ }
+
+ /* Append string terminator */
+ FileBuffer[FileLength] = 0;
+
+ NtClose(FileHandle);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtReadFile() failed (Status %lx)\n", Status);
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ FileBuffer);
+ return(Status);
+ }
+
+
+ /* Allocate inicache header */
+ *Cache = (PINICACHE)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(INICACHE));
+ if (*Cache == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ /* Initialize inicache header */
+ RtlZeroMemory(*Cache,
+ sizeof(INICACHE));
+
+ /* Parse ini file */
+ Section = NULL;
+ Ptr = FileBuffer;
+ while (Ptr != NULL && *Ptr != 0)
+ {
+ Ptr = IniCacheSkipWhitespace(Ptr);
+ if (Ptr == NULL)
+ continue;
+
+ if (*Ptr == '[')
+ {
+ Section = NULL;
+ Ptr++;
+
+ Ptr = IniCacheGetSectionName(Ptr,
+ &SectionName,
+ &SectionNameSize);
+
+ DPRINT1("[%.*s]\n", SectionNameSize, SectionName);
+
+ Section = IniCacheAddSection(*Cache,
+ SectionName,
+ SectionNameSize);
+ if (Section == NULL)
+ {
+ DPRINT("IniCacheAddSection() failed\n");
+ Ptr = IniCacheSkipToNextSection(Ptr);
+ continue;
+ }
+ }
+ else
+ {
+ if (Section == NULL)
+ {
+ Ptr = IniCacheSkipToNextSection(Ptr);
+ continue;
+ }
+
+ Ptr = IniCacheGetKeyName(Ptr,
+ &KeyName,
+ &KeyNameSize);
+
+ Ptr = IniCacheGetKeyValue(Ptr,
+ &KeyValue,
+ &KeyValueSize,
+ String);
+
+ DPRINT1("'%.*s' = '%.*s'\n", KeyNameSize, KeyName, KeyValueSize, KeyValue);
+
+ Key = IniCacheAddKey(Section,
+ KeyName,
+ KeyNameSize,
+ KeyValue,
+ KeyValueSize);
+ if (Key == NULL)
+ {
+ DPRINT("IniCacheAddKey() failed\n");
+ }
+ }
+ }
+
+ /* Free file buffer */
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ FileBuffer);
+
+ return(Status);
+}
+
+
+VOID
+IniCacheDestroy(PINICACHE Cache)
+{
+ if (Cache == NULL)
+ {
+ return;
+ }
+
+ while (Cache->FirstSection != NULL)
+ {
+ Cache->FirstSection = IniCacheFreeSection(Cache->FirstSection);
+ }
+ Cache->LastSection = NULL;
+
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Cache);
+}
+
+
+PINICACHESECTION
+IniCacheGetSection(PINICACHE Cache,
+ PWCHAR Name)
+{
+ PINICACHESECTION Section = NULL;
+
+ if (Cache == NULL || Name == NULL)
+ {
+ DPRINT("Invalid parameter\n");
+ return(NULL);
+ }
+
+ /* Iterate through list of sections */
+ Section = Cache->FirstSection;
+ while (Section != NULL)
+ {
+ DPRINT("Comparing '%S' and '%S'\n", Section->Name, Name);
+
+ /* Are the section names the same? */
+ if (_wcsicmp(Section->Name, Name) == 0)
+ return(Section);
+
+ /* Get the next section */
+ Section = Section->Next;
+ }
+
+ DPRINT("Section not found\n");
+
+ return(NULL);
+}
+
+
+NTSTATUS
+IniCacheGetKey(PINICACHESECTION Section,
+ PWCHAR KeyName,
+ PWCHAR *KeyData)
+{
+ PINICACHEKEY Key;
+
+ if (Section == NULL || KeyName == NULL || KeyData == NULL)
+ {
+ DPRINT("Invalid parameter\n");
+ return(STATUS_INVALID_PARAMETER);
+ }
+
+ *KeyData = NULL;
+
+ Key = IniCacheFindKey(Section, KeyName, wcslen(KeyName));
+ if (Key == NULL)
+ {
+ return(STATUS_INVALID_PARAMETER);
+ }
+
+ *KeyData = Key->Data;
+
+ return(STATUS_SUCCESS);
+}
+
+
+PINICACHEITERATOR
+IniCacheFindFirstValue(PINICACHESECTION Section,
+ PWCHAR *KeyName,
+ PWCHAR *KeyData)
+{
+ PINICACHEITERATOR Iterator;
+ PINICACHEKEY Key;
+
+ if (Section == NULL || KeyName == NULL || KeyData == NULL)
+ {
+ DPRINT("Invalid parameter\n");
+ return(NULL);
+ }
+
+ Key = Section->FirstKey;
+ if (Key == NULL)
+ {
+ DPRINT("Invalid parameter\n");
+ return(NULL);
+ }
+
+ *KeyName = Key->Name;
+ *KeyData = Key->Data;
+
+ Iterator = (PINICACHEITERATOR)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(INICACHEITERATOR));
+ if (Iterator == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ return(NULL);
+ }
+
+ Iterator->Section = Section;
+ Iterator->Key = Key;
+
+ return(Iterator);
+}
+
+
+BOOLEAN
+IniCacheFindNextValue(PINICACHEITERATOR Iterator,
+ PWCHAR *KeyName,
+ PWCHAR *KeyData)
+{
+ PINICACHEKEY Key;
+
+ if (Iterator == NULL || KeyName == NULL || KeyData == NULL)
+ {
+ DPRINT("Invalid parameter\n");
+ return(FALSE);
+ }
+
+ Key = Iterator->Key->Next;
+ if (Key == NULL)
+ {
+ DPRINT("No more entries\n");
+ return(FALSE);
+ }
+
+ *KeyName = Key->Name;
+ *KeyData = Key->Data;
+
+ Iterator->Key = Key;
+
+ return(TRUE);
+}
+
+
+VOID
+IniCacheFindClose(PINICACHEITERATOR Iterator)
+{
+ if (Iterator == NULL)
+ return;
+
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Iterator);
+}
+
+
+PINICACHEKEY
+IniCacheInsertKey(PINICACHESECTION Section,
+ PINICACHEKEY AnchorKey,
+ INSERTATION_TYPE InsertationType,
+ PWCHAR Name,
+ PWCHAR Data)
+{
+ PINICACHEKEY Key;
+ ULONG i;
+
+ Key = NULL;
+
+ if (Section == NULL ||
+ Name == NULL ||
+ *Name == 0 ||
+ Data == NULL ||
+ *Data == 0)
+ {
+ DPRINT("Invalid parameter\n");
+ return(NULL);
+ }
+
+ /* Allocate key buffer */
+ Key = (PINICACHEKEY)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(INICACHEKEY));
+ if (Key == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ return(NULL);
+ }
+ RtlZeroMemory(Key,
+ sizeof(INICACHEKEY));
+
+ /* Allocate name buffer */
+ Key->Name = RtlAllocateHeap(ProcessHeap,
+ 0,
+ (wcslen(Name) + 1) * sizeof(WCHAR));
+ if (Key->Name == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Key);
+ return(NULL);
+ }
+
+ /* Copy value name */
+ wcscpy(Key->Name, Name);
+
+ /* Allocate data buffer */
+ Key->Data = RtlAllocateHeap(ProcessHeap,
+ 0,
+ (wcslen(Data) + 1) * sizeof(WCHAR));
+ if (Key->Data == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Key->Name);
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Key);
+ return(NULL);
+ }
+
+ /* Copy value data */
+ wcscpy(Key->Data, Data);
+
+ /* Insert key into section */
+ if (Section->FirstKey == NULL)
+ {
+ Section->FirstKey = Key;
+ Section->LastKey = Key;
+ }
+ else if ((InsertationType == INSERT_FIRST) ||
+ ((InsertationType == INSERT_BEFORE) && ((AnchorKey == NULL) || (AnchorKey == Section->FirstKey))))
+ {
+ /* Insert at the head of the list */
+ Section->FirstKey->Prev = Key;
+ Key->Next = Section->FirstKey;
+ Section->FirstKey = Key;
+ }
+ else if ((InsertationType == INSERT_BEFORE) && (AnchorKey != NULL))
+ {
+ /* Insert before the anchor key */
+ Key->Next = AnchorKey;
+ Key->Prev = AnchorKey->Prev;
+ AnchorKey->Prev->Next = Key;
+ AnchorKey->Prev = Key;
+ }
+ else if ((InsertationType == INSERT_LAST) ||
+ ((InsertationType == INSERT_AFTER) && ((AnchorKey == NULL) || (AnchorKey == Section->LastKey))))
+ {
+ Section->LastKey->Next = Key;
+ Key->Prev = Section->LastKey;
+ Section->LastKey = Key;
+ }
+ else if ((InsertationType == INSERT_AFTER) && (AnchorKey != NULL))
+ {
+ /* Insert before the anchor key */
+ Key->Next = AnchorKey->Next;
+ Key->Prev = AnchorKey;
+ AnchorKey->Next->Prev = Key;
+ AnchorKey->Next = Key;
+ }
+
+ return(Key);
+}
+
+
+PINICACHE
+IniCacheCreate(VOID)
+{
+ PINICACHE Cache;
+
+ /* Allocate inicache header */
+ Cache = (PINICACHE)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(INICACHE));
+ if (Cache == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ return(NULL);
+ }
+
+ /* Initialize inicache header */
+ RtlZeroMemory(Cache,
+ sizeof(INICACHE));
+
+ return(Cache);
+}
+
+
+NTSTATUS
+IniCacheSave(PINICACHE Cache,
+ PWCHAR FileName)
+{
+ UNICODE_STRING Name;
+ PINICACHESECTION Section;
+ PINICACHEKEY Key;
+ ULONG BufferSize;
+ PCHAR Buffer;
+ PCHAR Ptr;
+ ULONG Len;
+ NTSTATUS Status;
+
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ LARGE_INTEGER Offset;
+ HANDLE FileHandle;
+
+
+ /* Calculate required buffer size */
+ BufferSize = 0;
+ Section = Cache->FirstSection;
+ while (Section != NULL)
+ {
+ BufferSize += (Section->Name ? wcslen(Section->Name) : 0)
+ + 4; /* "[]\r\n" */
+
+ Key = Section->FirstKey;
+ while (Key != NULL)
+ {
+ BufferSize += wcslen(Key->Name)
+ + (Key->Data ? wcslen(Key->Data) : 0)
+ + 3; /* "=\r\n" */
+ Key = Key->Next;
+ }
+
+ Section = Section->Next;
+ if (Section != NULL)
+ BufferSize += 2; /* extra "\r\n" at end of each section */
+ }
+ BufferSize++; /* Null-terminator */
+
+ DPRINT1("BufferSize: %lu\n", BufferSize);
+
+ /* Allocate file buffer */
+ Buffer = RtlAllocateHeap(ProcessHeap,
+ 0,
+ BufferSize);
+ if (Buffer == NULL)
+ {
+ DPRINT1("RtlAllocateHeap() failed\n");
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+ RtlZeroMemory(Buffer, BufferSize);
+
+ /* Fill file buffer */
+ Ptr = Buffer;
+ Section = Cache->FirstSection;
+ while (Section != NULL)
+ {
+ Len = sprintf(Ptr, "[%S]\r\n", Section->Name);
+ Ptr += Len;
+
+ Key = Section->FirstKey;
+ while (Key != NULL)
+ {
+ Len = sprintf(Ptr, "%S=%S\r\n", Key->Name, Key->Data);
+ Ptr += Len;
+ Key = Key->Next;
+ }
+
+ Section = Section->Next;
+ if (Section != NULL)
+ {
+ Len = sprintf(Ptr, "\r\n");
+ Ptr += Len;
+ }
+ }
+
+ /* Create ini file */
+ RtlInitUnicodeString(&Name,
+ FileName);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &Name,
+ 0,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&FileHandle,
+ FILE_WRITE_ACCESS,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_SUPERSEDE,
+ FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Buffer);
+ return(Status);
+ }
+
+ Offset.QuadPart = 0LL;
+ Status = NtWriteFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ Buffer,
+ BufferSize,
+ &Offset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
+ NtClose(FileHandle);
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Buffer);
+ return(Status);
+ }
+
+ NtClose(FileHandle);
+
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Buffer);
+
+ return(STATUS_SUCCESS);
+}
+
+
+PINICACHESECTION
+IniCacheAppendSection(PINICACHE Cache,
+ PWCHAR Name)
+{
+ PINICACHESECTION Section = NULL;
+ ULONG i;
+
+ if (Cache == NULL || Name == NULL || *Name == 0)
+ {
+ DPRINT("Invalid parameter\n");
+ return(NULL);
+ }
+
+ Section = (PINICACHESECTION)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(INICACHESECTION));
+ if (Section == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ return(NULL);
+ }
+ RtlZeroMemory(Section,
+ sizeof(INICACHESECTION));
+
+ /* Allocate and initialize section name */
+ Section->Name = RtlAllocateHeap(ProcessHeap,
+ 0,
+ (wcslen(Name) + 1) * sizeof(WCHAR));
+ if (Section->Name == NULL)
+ {
+ DPRINT("RtlAllocateHeap() failed\n");
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Section);
+ return(NULL);
+ }
+
+ /* Copy section name */
+ wcscpy(Section->Name, Name);
+
+ /* Append section */
+ if (Cache->FirstSection == NULL)
+ {
+ Cache->FirstSection = Section;
+ Cache->LastSection = Section;
+ }
+ else
+ {
+ Cache->LastSection->Next = Section;
+ Section->Prev = Cache->LastSection;
+ Cache->LastSection = Section;
+ }
+
+ return(Section);
+}
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2002 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS text-mode setup
+ * FILE: subsys/system/usetup/inicache.h
+ * PURPOSE: INI file parser that caches contents of INI file in memory
+ * PROGRAMMER: Royce Mitchell III
+ * Eric Kohl
+ */
+
+#ifndef __INICACHE_H__
+#define __INICACHE_H__
+
+
+typedef struct _INICACHEKEY
+{
+ PWCHAR Name;
+ PWCHAR Data;
+
+ struct _INICACHEKEY *Next;
+ struct _INICACHEKEY *Prev;
+} INICACHEKEY, *PINICACHEKEY;
+
+
+typedef struct _INICACHESECTION
+{
+ PWCHAR Name;
+
+ PINICACHEKEY FirstKey;
+ PINICACHEKEY LastKey;
+
+ struct _INICACHESECTION *Next;
+ struct _INICACHESECTION *Prev;
+} INICACHESECTION, *PINICACHESECTION;
+
+
+typedef struct _INICACHE
+{
+ PINICACHESECTION FirstSection;
+ PINICACHESECTION LastSection;
+} INICACHE, *PINICACHE;
+
+
+typedef struct _PINICACHEITERATOR
+{
+ PINICACHESECTION Section;
+ PINICACHEKEY Key;
+} INICACHEITERATOR, *PINICACHEITERATOR;
+
+
+typedef enum
+{
+ INSERT_FIRST,
+ INSERT_BEFORE,
+ INSERT_AFTER,
+ INSERT_LAST
+} INSERTATION_TYPE;
+
+/* FUNCTIONS ****************************************************************/
+
+NTSTATUS
+IniCacheLoad(PINICACHE *Cache,
+ PUNICODE_STRING FileName,
+ BOOL String);
+
+VOID
+IniCacheDestroy(PINICACHE Cache);
+
+PINICACHESECTION
+IniCacheGetSection(PINICACHE Cache,
+ PWCHAR Name);
+
+NTSTATUS
+IniCacheGetKey(PINICACHESECTION Section,
+ PWCHAR KeyName,
+ PWCHAR *KeyData);
+
+
+
+PINICACHEITERATOR
+IniCacheFindFirstValue(PINICACHESECTION Section,
+ PWCHAR *KeyName,
+ PWCHAR *KeyData);
+
+BOOLEAN
+IniCacheFindNextValue(PINICACHEITERATOR Iterator,
+ PWCHAR *KeyName,
+ PWCHAR *KeyData);
+
+VOID
+IniCacheFindClose(PINICACHEITERATOR Iterator);
+
+
+PINICACHEKEY
+IniCacheInsertKey(PINICACHESECTION Section,
+ PINICACHEKEY AnchorKey,
+ INSERTATION_TYPE InsertationType,
+ PWCHAR Name,
+ PWCHAR Data);
+
+PINICACHE
+IniCacheCreate(VOID);
+
+NTSTATUS
+IniCacheSave(PINICACHE Cache,
+ PWCHAR FileName);
+
+PINICACHESECTION
+IniCacheAppendSection(PINICACHE Cache,
+ PWCHAR Name);
+
+
+#endif /* __INICACHE_H__ */
+
+/* EOF */
--- /dev/null
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <ntdll/rtl.h>
+
+#include "usetup.h"
+#include "progress.h"
+
+/* FUNCTIONS ****************************************************************/
+
+
+static VOID
+DrawBorder(PPROGRESS Bar)
+{
+ COORD coPos;
+ ULONG Written;
+ SHORT i;
+
+ /* draw upper left corner */
+ coPos.X = Bar->Left;
+ coPos.Y = Bar->Top + 1;
+ FillConsoleOutputCharacter(0xDA, // '+',
+ 1,
+ coPos,
+ &Written);
+
+ /* draw upper edge */
+ coPos.X = Bar->Left + 1;
+ coPos.Y = Bar->Top + 1;
+ FillConsoleOutputCharacter(0xC4, // '-',
+ Bar->Right - Bar->Left - 1,
+ coPos,
+ &Written);
+
+ /* draw upper right corner */
+ coPos.X = Bar->Right;
+ coPos.Y = Bar->Top + 1;
+ FillConsoleOutputCharacter(0xBF, // '+',
+ 1,
+ coPos,
+ &Written);
+
+ /* draw left and right edge */
+ for (i = Bar->Top + 2; i < Bar->Bottom; i++)
+ {
+ coPos.X = Bar->Left;
+ coPos.Y = i;
+ FillConsoleOutputCharacter(0xB3, // '|',
+ 1,
+ coPos,
+ &Written);
+
+ coPos.X = Bar->Right;
+ FillConsoleOutputCharacter(0xB3, //'|',
+ 1,
+ coPos,
+ &Written);
+ }
+
+ /* draw lower left corner */
+ coPos.X = Bar->Left;
+ coPos.Y = Bar->Bottom;
+ FillConsoleOutputCharacter(0xC0, // '+',
+ 1,
+ coPos,
+ &Written);
+
+ /* draw lower edge */
+ coPos.X = Bar->Left + 1;
+ coPos.Y = Bar->Bottom;
+ FillConsoleOutputCharacter(0xC4, // '-',
+ Bar->Right - Bar->Left - 1,
+ coPos,
+ &Written);
+
+ /* draw lower right corner */
+ coPos.X = Bar->Right;
+ coPos.Y = Bar->Bottom;
+ FillConsoleOutputCharacter(0xD9, // '+',
+ 1,
+ coPos,
+ &Written);
+}
+
+
+static VOID
+DrawProgressBar(PPROGRESS Bar)
+{
+ CHAR TextBuffer[8];
+ COORD coPos;
+ ULONG Written;
+ SHORT i;
+
+ /* Print percentage */
+ sprintf(TextBuffer, "%-3lu%%", Bar->Percent);
+
+ coPos.X = Bar->Left + (Bar->Width - 2) / 2;
+ coPos.Y = Bar->Top;
+ WriteConsoleOutputCharacters(TextBuffer,
+ 4,
+ coPos);
+
+ DrawBorder(Bar);
+
+ /* Draw the bar */
+ coPos.X = Bar->Left + 1;
+ for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++)
+ {
+ FillConsoleOutputAttribute(0x1E, /* Yellow on blue */
+ Bar->Width - 2,
+ coPos,
+ &Written);
+
+ FillConsoleOutputCharacter(' ',
+ Bar->Width - 2,
+ coPos,
+ &Written);
+ }
+
+}
+
+
+
+PPROGRESS
+CreateProgressBar(SHORT Left,
+ SHORT Top,
+ SHORT Right,
+ SHORT Bottom)
+{
+ PPROGRESS Bar;
+
+ Bar = (PPROGRESS)RtlAllocateHeap(ProcessHeap,
+ 0,
+ sizeof(PROGRESS));
+ if (Bar == NULL)
+ return(NULL);
+
+ Bar->Left = Left;
+ Bar->Top = Top;
+ Bar->Right = Right;
+ Bar->Bottom = Bottom;
+
+ Bar->Width = Bar->Right - Bar->Left + 1;
+
+ Bar->Percent = 0;
+ Bar->Pos = 0;
+
+ Bar->StepCount = 0;
+ Bar->CurrentStep = 0;
+
+ DrawProgressBar(Bar);
+
+ return(Bar);
+}
+
+
+VOID
+DestroyProgressBar(PPROGRESS Bar)
+{
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ Bar);
+}
+
+VOID
+ProgressSetStepCount(PPROGRESS Bar,
+ ULONG StepCount)
+{
+ Bar->CurrentStep = 0;
+ Bar->StepCount = StepCount;
+
+ DrawProgressBar(Bar);
+}
+
+
+VOID
+ProgressNextStep(PPROGRESS Bar)
+{
+ CHAR TextBuffer[8];
+ COORD coPos;
+ ULONG Written;
+ ULONG NewPercent;
+ ULONG NewPos;
+
+ if ((Bar->StepCount == 0) ||
+ (Bar->CurrentStep == Bar->StepCount))
+ return;
+
+ Bar->CurrentStep++;
+
+ /* Calculate new percentage */
+ NewPercent = (ULONG)(((100.0 * (float)Bar->CurrentStep) / (float)Bar->StepCount) + 0.5);
+
+ /* Redraw precentage if changed */
+ if (Bar->Percent != NewPercent)
+ {
+ Bar->Percent = NewPercent;
+
+ sprintf(TextBuffer, "%-3lu%%", Bar->Percent);
+
+ coPos.X = Bar->Left + (Bar->Width - 2) / 2;
+ coPos.Y = Bar->Top;
+ WriteConsoleOutputCharacters(TextBuffer,
+ 4,
+ coPos);
+ }
+
+ /* Calculate bar position */
+ NewPos = (ULONG)((((float)(Bar->Width - 2) * 2.0 * (float)Bar->CurrentStep) / (float)Bar->StepCount) + 0.5);
+
+ /* Redraw bar if changed */
+ if (Bar->Pos != NewPos)
+ {
+ Bar->Pos = NewPos;
+
+ for (coPos.Y = Bar->Top + 2; coPos.Y <= Bar->Bottom - 1; coPos.Y++)
+ {
+ coPos.X = Bar->Left + 1;
+ FillConsoleOutputCharacter(0xDB,
+ Bar->Pos / 2,
+ coPos,
+ &Written);
+ coPos.X += Bar->Pos/2;
+
+ if (Pos & 1)
+ {
+ FillConsoleOutputCharacter(0xDD,
+ 1,
+ coPos,
+ &Written);
+ coPos.X++;
+ }
+
+ if (coPos.X <= Bar->Right - 1)
+ {
+ FillConsoleOutputCharacter(' ',
+ Bar->Right - coPos.X,
+ coPos,
+ &Written);
+ }
+ }
+ }
+}
+
+/* EOF */
--- /dev/null
+/*
+ * ReactOS kernel
+ * Copyright (C) 2002 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS text-mode setup
+ * FILE: subsys/system/usetup/partlist.h
+ * PURPOSE: Partition list functions
+ * PROGRAMMER: Eric Kohl
+ */
+
+#ifndef __PROGRESS_H__
+#define __PROGRESS_H__
+
+
+typedef struct _PROGRESS
+{
+ SHORT Left;
+ SHORT Top;
+ SHORT Right;
+ SHORT Bottom;
+
+ SHORT Width;
+
+ ULONG Percent;
+ ULONG Pos;
+
+ ULONG StepCount;
+ ULONG CurrentStep;
+} PROGRESS, *PPROGRESS;
+
+/* FUNCTIONS ****************************************************************/
+
+PPROGRESS
+CreateProgressBar(SHORT Left,
+ SHORT Top,
+ SHORT Right,
+ SHORT Bottom);
+
+VOID
+DestroyProgressBar(PPROGRESS Bar);
+
+VOID
+ProgressSetStepCount(PPROGRESS Bar,
+ ULONG StepCount);
+
+VOID
+ProgressNextStep(PPROGRESS Bar);
+
+#endif /* __PROGRESS_H__ */
+
+/* EOF */
\ No newline at end of file
--- /dev/null
+/* $Id$
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: Scrollbars
+ * FILE: subsys/win32k/ntuser/scrollbar.c
+ * PROGRAMER: Jason Filby (jasonfilby@yahoo.com)
+ * REVISION HISTORY:
+ * 16-11-2002 Jason Filby Created
+ */
+/* INCLUDES ******************************************************************/
+
+#include <ddk/ntddk.h>
+#include <win32k/win32k.h>
+#include <include/object.h>
+#include <include/window.h>
+#include <include/class.h>
+#include <include/error.h>
+#include <include/winsta.h>
+#include <include/winpos.h>
+#include <include/rect.h>
+
+//#define NDEBUG
+#include <debug.h>
+
+#define SCROLL_MIN_RECT 4 /* Minimum size of the rectangle between the arrows */
+#define SCROLL_ARROW_THUMB_OVERLAP 0 /* Overlap between arrows and thumb */
+
+/* FUNCTIONS *****************************************************************/
+
+/* Ported from WINE20020904 */
+/* Compute the scroll bar rectangle, in drawing coordinates (i.e. client coords for SB_CTL, window coords for SB_VERT and
+ * SB_HORZ). 'arrowSize' returns the width or height of an arrow (depending on * the orientation of the scrollbar),
+ * 'thumbSize' returns the size of the thumb, and 'thumbPos' returns the position of the thumb relative to the left or to
+ * the top. Return TRUE if the scrollbar is vertical, FALSE if horizontal.
+ */
+static BOOL
+SCROLL_GetScrollBarRect (PWINDOW_OBJECT Window, INT nBar, PRECT lprect)
+{
+ SCROLLBARINFO info;
+ INT pixels, thumbSize, arrowSize;
+ BOOL vertical;
+ RECT ClientRect = Window->ClientRect;
+ RECT WindowRect = Window->WindowRect;
+ ULONG Style;
+
+ switch (nBar)
+ {
+ case SB_HORZ:
+ lprect->left = ClientRect.left - WindowRect.left;
+ lprect->top = ClientRect.bottom - WindowRect.top;
+ lprect->right = ClientRect.right - WindowRect.left;
+ lprect->bottom = lprect->top + NtUserGetSystemMetrics (SM_CYHSCROLL);
+ if (Window->Style & WS_BORDER)
+ {
+ lprect->left--;
+ lprect->right++;
+ }
+ else if (Window->Style & WS_VSCROLL)
+ lprect->right++;
+ vertical = FALSE;
+ break;
+
+ case SB_VERT:
+ lprect->left = ClientRect.right - WindowRect.left;
+ lprect->top = ClientRect.top - WindowRect.top;
+ lprect->right = lprect->left + NtUserGetSystemMetrics (SM_CXVSCROLL);
+ lprect->bottom = ClientRect.bottom - WindowRect.top;
+ if (Window->Style & WS_BORDER)
+ {
+ lprect->top--;
+ lprect->bottom++;
+ }
+ else if (Window->Style & WS_HSCROLL)
+ lprect->bottom++;
+ vertical = TRUE;
+ break;
+
+ case SB_CTL:
+ W32kGetClientRect (Window, lprect);
+ vertical = ((Window->Style & SBS_VERT) != 0);
+ break;
+
+ default:
+ W32kReleaseWindowObject(Window);
+ return FALSE;
+ }
+
+ if (vertical)
+ pixels = lprect->bottom - lprect->top;
+ else
+ pixels = lprect->right - lprect->left;
+
+ info.cbSize = sizeof(SCROLLBARINFO);
+ SCROLL_GetScrollBarInfo (Window, nBar, &info);
+
+ if (pixels <= 2 * NtUserGetSystemMetrics (SM_CXVSCROLL) + SCROLL_MIN_RECT)
+ {
+ info.dxyLineButton = info.xyThumbTop = info.xyThumbBottom = 0;
+ }
+ else
+ {
+ arrowSize = NtUserGetSystemMetrics (SM_CXVSCROLL);
+ pixels -= (2 * (NtUserGetSystemMetrics (SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP));
+
+ /* Temporary initialization - to be removed once proper code is in */
+ info.dxyLineButton = info.xyThumbTop = info.xyThumbBottom = 0;
+
+/* if (info->Page)
+ {
+ thumbSize = MulDiv(pixels,info->Page,(info->MaxVal-info->MinVal+1));
+ if (*thumbSize < SCROLL_MIN_THUMB) *thumbSize = SCROLL_MIN_THUMB;
+ }
+ else *thumbSize = NtUserGetSystemMetrics(SM_CXVSCROLL); */
+/*
+ if (((pixels -= *thumbSize ) < 0) ||
+ ((info->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH))
+ { */
+ /* Rectangle too small or scrollbar disabled -> no thumb */
+/* *thumbPos = *thumbSize = 0;
+ }
+ else
+ { */
+/* INT max = info->MaxVal - max( info->Page-1, 0 );
+ if (info->MinVal >= max)
+ *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
+ else
+ *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP
+ + MulDiv(pixels, (info->CurVal-info->MinVal),(max - info->MinVal));
+ } */
+ }
+
+ return vertical;
+}
+
+DWORD SCROLL_CreateScrollBar(PWINDOW_OBJECT Window, LONG idObject)
+{
+ PSCROLLBARINFO psbi;
+ LRESULT Result;
+ INT i;
+
+ Result = WinPosGetNonClientSize(Window->Self,
+ &Window->WindowRect,
+ &Window->ClientRect);
+
+ psbi = ExAllocatePool(NonPagedPool, sizeof(SCROLLBARINFO));
+
+ for (i=0; i<CCHILDREN_SCROLLBAR+1; i++)
+ psbi->rgstate[i] = 0;
+
+ switch(idObject)
+ {
+ case SB_HORZ:
+ Window->pHScroll = psbi;
+ break;
+ case SB_VERT:
+ Window->pVScroll = psbi;
+ break;
+ case SB_CTL:
+ Window->wExtra = psbi;
+ break;
+ default:
+ return FALSE;
+ }
+
+ SCROLL_GetScrollBarRect (Window, idObject, &(psbi->rcScrollBar));
+
+ return 0;
+}
+
+DWORD SCROLL_GetScrollBarInfo(PWINDOW_OBJECT Window, LONG idObject, PSCROLLBARINFO psbi)
+{
+ switch(idObject)
+ {
+ case SB_HORZ:
+ memcpy(psbi, Window->pHScroll, psbi->cbSize);
+ break;
+ case SB_VERT:
+ memcpy(psbi, Window->pVScroll, psbi->cbSize);
+ break;
+ case SB_CTL:
+ memcpy(psbi, Window->wExtra, psbi->cbSize);
+ break;
+ default:
+ W32kReleaseWindowObject(Window);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+DWORD
+STDCALL
+NtUserGetScrollBarInfo(HWND hWnd, LONG idObject, PSCROLLBARINFO psbi)
+{
+ PWINDOW_OBJECT Window = W32kGetWindowObject(hWnd);
+
+ if (!Window) return FALSE;
+
+ SCROLL_GetScrollBarInfo(Window, idObject, psbi);
+
+ W32kReleaseWindowObject(Window);
+
+ return TRUE;
+}
+
+DWORD
+STDCALL
+NtUserEnableScrollBar(
+ DWORD Unknown0,
+ DWORD Unknown1,
+ DWORD Unknown2)
+{
+ return 0;
+}
+
+DWORD
+STDCALL
+NtUserScrollDC(
+ DWORD Unknown0,
+ DWORD Unknown1,
+ DWORD Unknown2,
+ DWORD Unknown3,
+ DWORD Unknown4,
+ DWORD Unknown5,
+ DWORD Unknown6)
+
+{
+ UNIMPLEMENTED
+
+ return 0;
+}
+
+DWORD
+STDCALL
+NtUserSetScrollInfo(
+ DWORD Unknown0,
+ DWORD Unknown1,
+ DWORD Unknown2,
+ DWORD Unknown3)
+{
+ UNIMPLEMENTED
+
+ return 0;
+}
+
+/* Ported from WINE20020904 (SCROLL_ShowScrollBar) */
+DWORD
+STDCALL
+NtUserShowScrollBar(HWND hWnd, int wBar, DWORD bShow)
+{
+ BOOL fShowV = (wBar == SB_VERT) ? 0 : bShow;
+ BOOL fShowH = (wBar == SB_HORZ) ? 0 : bShow;
+ PWINDOW_OBJECT Window = W32kGetWindowObject(hWnd);
+
+ switch (wBar)
+ {
+ case SB_CTL:
+ NtUserShowWindow (hWnd, fShowH ? SW_SHOW : SW_HIDE);
+ return TRUE;
+
+ case SB_BOTH:
+ case SB_HORZ:
+ if (fShowH)
+ {
+ fShowH = !(Window->Style & WS_HSCROLL);
+ Window->Style |= WS_HSCROLL;
+ }
+ else /* hide it */
+ {
+ fShowH = (Window->Style & WS_HSCROLL);
+ Window->Style &= ~WS_HSCROLL;
+ }
+ if (wBar == SB_HORZ)
+ {
+ fShowV = FALSE;
+ break;
+ }
+ /* fall through */
+
+ case SB_VERT:
+ if (fShowV)
+ {
+ fShowV = !(Window->Style & WS_VSCROLL);
+ Window->Style |= WS_VSCROLL;
+ }
+ else /* hide it */
+ {
+ fShowV = (Window->Style & WS_VSCROLL);
+ Window->Style &= ~WS_VSCROLL;
+ }
+ if (wBar == SB_VERT)
+ fShowH = FALSE;
+ break;
+
+ default:
+ return FALSE; /* Nothing to do! */
+ }
+
+ if (fShowH || fShowV) /* frame has been changed, let the window redraw itself */
+ {
+ NtUserSetWindowPos (hWnd, 0, 0, 0, 0, 0,
+ SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
+ return TRUE;
+ }
+ return FALSE; /* no frame changes */
+}
+
+/* EOF */
--- /dev/null
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef WIN32
+#include <sys/utime.h>
+#else
+#include <sys/time.h>
+#include <stdlib.h>
+#endif
+
+#include <fcntl.h>
+#include <stdio.h>
+
+char* convert_path(char* origpath)
+{
+ char* newpath;
+ int i;
+
+ newpath = (char *)strdup(origpath);
+
+ i = 0;
+ while (newpath[i] != 0)
+ {
+#ifdef UNIX_PATHS
+ if (newpath[i] == '\\')
+ {
+ newpath[i] = '/';
+ }
+#else
+#ifdef DOS_PATHS
+ if (newpath[i] == '/')
+ {
+ newpath[i] = '\\';
+ }
+#endif
+#endif
+ i++;
+ }
+ return(newpath);
+}
+
+int main(int argc, char* argv[])
+{
+ char* path;
+ FILE* file;
+#ifdef WIN32
+ time_t now;
+ struct utimbuf fnow;
+#endif
+
+ if (argc != 2)
+ {
+ fprintf(stderr, "Wrong number of arguments.\n");
+ exit(1);
+ }
+
+ path = convert_path(argv[1]);
+ file = (FILE *)open(path, S_IWRITE);
+ if (file == (void*)-1)
+ {
+ file = (FILE *)open(path, S_IWRITE | O_CREAT);
+ if (file == (void*)-1)
+ {
+ fprintf(stderr, "Cannot create file.\n");
+ exit(1);
+ }
+ }
+
+ fclose(file);
+
+#ifdef WIN32
+ now = time();
+ fnow.actime = now;
+ fnow.modtime = now;
+ (int) utime(path, &fnow);
+#else
+ (int) utimes(path, NULL);
+#endif
+
+ exit(0);
+}
--- /dev/null
+[Version]
+Signature = "$ReactOS$"
+
+[Directories]
+1 = "\"
+2 = system32
+3 = system32\drivers
+4 = system32\config
+5 = media
+6 = media\fonts
+7 = bin
+
+[SourceFiles]
+ntoskrnl.exe = 2
+hal.dll = 2
+
+acpi.sys = 3
+isapnp.sys = 3
+
+beep.sys = 3
+blue.sys = 3
+floppy.sys = 3
+null.sys = 3
+serial.sys = 3
+vgaddi.dll = 3
+vgamp.sys = 3
+vidport.sys = 3
+
+cdfs.sys = 3
+fs_rec.sys = 3
+msfs.sys = 3
+mup.sys = 3
+npfs.sys = 3
+ntfs.sys = 3
+vfatfs.sys = 3
+
+keyboard.sys = 3
+mouclass.sys = 3
+psaux.sys = 3
+
+unbzip2.sys = 3
+
+afd.sys = 3
+ne2000.sys = 3
+ndis.sys = 3
+npf.sys = 3
+;packet.sys = 3
+tcpip.sys = 3
+tdi.sys = 3
+
+atapi.sys = 3
+cdrom.sys = 3
+class2.sys = 3
+disk.sys = 3
+scsiport.sys = 3
+
+advapi32.dll = 2
+crtdll.dll = 2
+fmifs.dll = 2
+gdi32.dll = 2
+kernel32.dll = 2
+msafd.dll = 2
+msvcrt.dll = 2
+ntdll.dll = 2
+;ole32.dll = 2
+;oleaut32.dll = 2
+packet.dll = 2
+secur32.dll = 2
+;shell32.dll = 2
+user32.dll = 2
+version.dll = 2
+winedbgc.dll = 2
+winmm.dll = 2
+ws2_32.dll = 2
+ws2help.dll = 2
+wshirda.dll = 2
+
+eventlog.exe = 2
+rpcss.exe = 2
+csrss.exe = 2
+ntvdm.exe = 2
+smss.exe = 2
+autochk.exe = 2
+gstart.exe = 2
+;lsass.exe = 2
+services.exe = 2
+shell.exe = 2
+winlogon.exe = 2
+
+win32k.sys = 3
+
+helb____.ttf = 6
+timr____.ttf = 6
+
+system.hiv = 4
+
+[SetupData]
+DefaultPath = \reactos