// ntdll import library test for D //module windows.native version(Windows) { pragma(lib, "advapi32.lib"); } else { static assert("Only Windows platform is supported - compile with version=Windows" is 0); } //import std.c.windows.windows; // for things like USHORT etc import win32.windef; // PWSTR import win32.winnt; // PSECURITY_DESCRIPTOR import win32.winreg; import std.loader; import std.stdio; // PATCHES // patches that should be reported to Walter & fixed alias WCHAR* PWSTR; // should I replace this mess with std.stdint.uintptr_t version(X86) { alias void* ULONG_PTR; // ULONG (windows type) & void* have the same sizes so ULONG_PTR is 32bit wide } version(X86_64) { alias void* ULONG_PTR; // void* is larger than ULONG (windows type) so ULONG_PTR is 64bit wide } extern (Windows) { export LONG RegOpenKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult); export LONG RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData); alias BOOL function (HANDLE hFile, out LARGE_INTEGER lpFileSize) GetFileSizeExFn; GetFileSizeExFn GetFileSizeEx; } // report to core32 maintainers that in winnt.d 1241: ACCESS_MASK is already defined in std.c.windows.windows // PATCHES - end alias LONG NTSTATUS; struct UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } alias UNICODE_STRING* PUNICODE_STRING; struct IO_STATUS_BLOCK { union { NTSTATUS Status; PVOID Pointer; }; ULONG_PTR Information; } alias IO_STATUS_BLOCK* PIO_STATUS_BLOCK; // // Definitions for Object Creation // enum ObjectCreationAttributes : ULONG { NONE = 0, OBJ_INHERIT = 0x00000002L, OBJ_PERMANENT = 0x00000010L, OBJ_EXCLUSIVE = 0x00000020L, OBJ_CASE_INSENSITIVE = 0x00000040L, OBJ_OPENIF = 0x00000080L, OBJ_OPENLINK = 0x00000100L, OBJ_KERNEL_HANDLE = 0x00000200L, OBJ_FORCE_ACCESS_CHECK = 0x00000400L, OBJ_VALID_ATTRIBUTES = 0x000007F2L } // // NtCreateFile Flags // enum FileCreateOptions : ULONG { FILE_DIRECTORY_FILE = 0x00000001, FILE_WRITE_THROUGH = 0x00000002, FILE_SEQUENTIAL_ONLY = 0x00000004, FILE_NO_INTERMEDIATE_BUFFERING = 0x00000008, FILE_SYNCHRONOUS_IO_ALERT = 0x00000010, FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020, FILE_NON_DIRECTORY_FILE = 0x00000040, FILE_CREATE_TREE_CONNECTION = 0x00000080, FILE_COMPLETE_IF_OPLOCKED = 0x00000100, FILE_NO_EA_KNOWLEDGE = 0x00000200, FILE_OPEN_FOR_RECOVERY = 0x00000400, FILE_RANDOM_ACCESS = 0x00000800, FILE_DELETE_ON_CLOSE = 0x00001000, FILE_OPEN_BY_FILE_ID = 0x00002000, FILE_OPEN_FOR_BACKUP_INTENT = 0x00004000, FILE_NO_COMPRESSION = 0x00008000, FILE_RESERVE_OPFILTER = 0x00100000, FILE_OPEN_REPARSE_POINT = 0x00200000, FILE_OPEN_NO_RECALL = 0x00400000, FILE_OPEN_FOR_FREE_SPACE_QUERY = 0x00800000 } struct OBJECT_ATTRIBUTES { ULONG Length; HANDLE RootDirectory; PUNICODE_STRING ObjectName; ObjectCreationAttributes Attributes; PVOID SecurityDescriptor; PVOID SecurityQualityOfService; } alias OBJECT_ATTRIBUTES* POBJECT_ATTRIBUTES; void InitializeObjectAttributes( POBJECT_ATTRIBUTES p, PUNICODE_STRING ObjectName, ObjectCreationAttributes Attributes = ObjectCreationAttributes.NONE, HANDLE RootDirectory = null, PSECURITY_DESCRIPTOR SecurityDescriptor = null) { p.Length = OBJECT_ATTRIBUTES.sizeof; p.RootDirectory = RootDirectory; p.ObjectName = ObjectName; p.Attributes = Attributes; p.SecurityDescriptor = SecurityDescriptor; p.SecurityQualityOfService = null; } void RtlInitUnicodeString(PUNICODE_STRING DestinationString, wchar[] SourceString) { assert(SourceString !is null && SourceString.ptr !is null); assert(SourceString.length*wchar.sizeof<=uint.max); DestinationString.Length = DestinationString.MaximumLength = cast(USHORT)(SourceString.length*wchar.sizeof); DestinationString.Buffer = SourceString.ptr; } extern(Windows) { alias NTSTATUS function ( out HANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, out IO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, FileCreateOptions OpenOptions ) NtOpenFileFn; NtOpenFileFn NtOpenFile; } class Win32Exception : Exception { this(LONG _res) { super("Win32 error"); this.res = _res; } LONG res; } wchar[] GetSystemPartition() { // SystemPartition path is stored in HKLM\System\Setup:SystemPartition" HKEY hKey; LONG res; res = RegOpenKeyW(HKEY_LOCAL_MACHINE, "System\\Setup"w, &hKey); if (res!=ERROR_SUCCESS) { throw new Win32Exception(res); } DWORD requiredSize = 0; wchar[] outcome = ""; // to force outcome.ptr not null while ( (res = RegQueryValueExW(hKey, "SystemPartition"w, null, null, cast(LPBYTE)outcome.ptr, &requiredSize)) == ERROR_MORE_DATA) { outcome.length = requiredSize - wchar.sizeof; // we needn't trailing NULL } RegCloseKey(hKey); if (res!=ERROR_SUCCESS) throw new Win32Exception(res); return outcome; } void main() { writefln("loading kernel32.dll"); auto ExeModule kernel32 = new ExeModule(`c:\winnt\system32\kernel32.dll`); writefln("loading GetFileSizeEx"); GetFileSizeEx = cast(GetFileSizeExFn) kernel32.getSymbol("GetFileSizeEx"); writefln("loading ntdll.dll"); auto ExeModule ntdll = new ExeModule(`c:\winnt\system32\ntdll.dll`); writefln("loading NtOpenFile"); NtOpenFile = cast(NtOpenFileFn) ntdll.getSymbol("NtOpenFile"); writefln("Native Functions test."); HANDLE h = INVALID_HANDLE_VALUE; try { wchar[] file_name = GetSystemPartition() ~ "\\boot.ini"w; OBJECT_ATTRIBUTES objAttr; UNICODE_STRING fileName; IO_STATUS_BLOCK outcome; RtlInitUnicodeString(&fileName, file_name); InitializeObjectAttributes(&objAttr, &fileName); NTSTATUS status = NtOpenFile( h, GENERIC_READ|SYNCHRONIZE, &objAttr, outcome, FILE_SHARE_READ|FILE_SHARE_WRITE, FileCreateOptions.FILE_SYNCHRONOUS_IO_NONALERT); if (status!=0 || h == INVALID_HANDLE_VALUE) { writefln("Error for NtOpenFile: 0x%x, 0x%x", status, h); return; } char[] content; DWORD bytesRead = 0; BOOL res; LARGE_INTEGER fileSize; res = GetFileSizeEx(h, fileSize); if (!res) return; if (fileSize.QuadPart>content.length.max) { writefln("Too large file"); return; } content.length = cast(uint)fileSize.QuadPart; res = ReadFile(h, content.ptr, content.length, &bytesRead, null); if (res==0) { writefln("Error for ReadFile: 0x%x", GetLastError()); return; } content.length = bytesRead; writefln(content); } finally { kernel32.close(); ntdll.close(); if (h!=INVALID_HANDLE_VALUE) CloseHandle(h); } }