From 8bb7ed968db64e9b12a6447e2eec3586ef9e935c Mon Sep 17 00:00:00 2001 From: Dirk Date: Tue, 10 Jun 2014 14:19:40 +0200 Subject: Windows system name changer during bootup. --- windows/bootpgm/BUILD | 8 + windows/bootpgm/build-interactive.bat.removethis | 2 + windows/bootpgm/build-release.bat.removethis | 2 + windows/bootpgm/dirs | 3 + windows/bootpgm/doc/exception.txt | 50 +++ windows/bootpgm/native/MAKEFILE | 7 + windows/bootpgm/native/SOURCES | 16 + windows/bootpgm/native/native.cpp | 427 ++++++++++++++++++++++ windows/bootpgm/native/newnative.h | 322 +++++++++++++++++ windows/bootpgm/win32/Handle.cpp | 293 +++++++++++++++ windows/bootpgm/win32/Handle.h | 90 +++++ windows/bootpgm/win32/IO.cpp | 136 +++++++ windows/bootpgm/win32/IO.h | 102 ++++++ windows/bootpgm/win32/MAKEFILE | 7 + windows/bootpgm/win32/Main.cpp | 220 ++++++++++++ windows/bootpgm/win32/Main.h | 90 +++++ windows/bootpgm/win32/RegistryBrowser.cpp | 71 ++++ windows/bootpgm/win32/RegistryBrowser.h | 19 + windows/bootpgm/win32/SOURCES | 25 ++ windows/bootpgm/win32/account.cpp | 60 ++++ windows/bootpgm/win32/account.h | 27 ++ windows/bootpgm/win32/computername.cpp | 435 +++++++++++++++++++++++ windows/bootpgm/win32/experimental.cpp | 275 ++++++++++++++ windows/bootpgm/win32/stdafx.cpp | 26 ++ windows/bootpgm/win32/stdafx.h | 50 +++ windows/bootpgm/win32/usermode-registry.sln | 23 ++ windows/bootpgm/win32/usermode-registry.vcproj | 365 +++++++++++++++++++ windows/bootpgm/win32/win32.cpp | 92 +++++ 28 files changed, 3243 insertions(+) create mode 100644 windows/bootpgm/BUILD create mode 100644 windows/bootpgm/build-interactive.bat.removethis create mode 100644 windows/bootpgm/build-release.bat.removethis create mode 100644 windows/bootpgm/dirs create mode 100644 windows/bootpgm/doc/exception.txt create mode 100644 windows/bootpgm/native/MAKEFILE create mode 100644 windows/bootpgm/native/SOURCES create mode 100644 windows/bootpgm/native/native.cpp create mode 100644 windows/bootpgm/native/newnative.h create mode 100644 windows/bootpgm/win32/Handle.cpp create mode 100644 windows/bootpgm/win32/Handle.h create mode 100644 windows/bootpgm/win32/IO.cpp create mode 100644 windows/bootpgm/win32/IO.h create mode 100644 windows/bootpgm/win32/MAKEFILE create mode 100644 windows/bootpgm/win32/Main.cpp create mode 100644 windows/bootpgm/win32/Main.h create mode 100644 windows/bootpgm/win32/RegistryBrowser.cpp create mode 100644 windows/bootpgm/win32/RegistryBrowser.h create mode 100644 windows/bootpgm/win32/SOURCES create mode 100644 windows/bootpgm/win32/account.cpp create mode 100644 windows/bootpgm/win32/account.h create mode 100644 windows/bootpgm/win32/computername.cpp create mode 100644 windows/bootpgm/win32/experimental.cpp create mode 100644 windows/bootpgm/win32/stdafx.cpp create mode 100644 windows/bootpgm/win32/stdafx.h create mode 100644 windows/bootpgm/win32/usermode-registry.sln create mode 100644 windows/bootpgm/win32/usermode-registry.vcproj create mode 100644 windows/bootpgm/win32/win32.cpp (limited to 'windows/bootpgm') diff --git a/windows/bootpgm/BUILD b/windows/bootpgm/BUILD new file mode 100644 index 00000000..d282ea57 --- /dev/null +++ b/windows/bootpgm/BUILD @@ -0,0 +1,8 @@ += How to build = + +== Boot Program == + +To build the boot program you need Windows 2000 DDK (others not tested). Start DDK Build command prompt and cd to this dir. Type build-interactive to build an boot program with interactive console. + +== Win32 Test Program == +Use the provided Visual C++ Express workspace (win32/usermode-registry.sln) to build. diff --git a/windows/bootpgm/build-interactive.bat.removethis b/windows/bootpgm/build-interactive.bat.removethis new file mode 100644 index 00000000..23113901 --- /dev/null +++ b/windows/bootpgm/build-interactive.bat.removethis @@ -0,0 +1,2 @@ +set cl=/DINTERACTIVE +build -cgw \ No newline at end of file diff --git a/windows/bootpgm/build-release.bat.removethis b/windows/bootpgm/build-release.bat.removethis new file mode 100644 index 00000000..69605338 --- /dev/null +++ b/windows/bootpgm/build-release.bat.removethis @@ -0,0 +1,2 @@ +set cl= +build -cg \ No newline at end of file diff --git a/windows/bootpgm/dirs b/windows/bootpgm/dirs new file mode 100644 index 00000000..2f59ee73 --- /dev/null +++ b/windows/bootpgm/dirs @@ -0,0 +1,3 @@ +DIRS= \ + win32\ + native \ No newline at end of file diff --git a/windows/bootpgm/doc/exception.txt b/windows/bootpgm/doc/exception.txt new file mode 100644 index 00000000..c0d22c36 --- /dev/null +++ b/windows/bootpgm/doc/exception.txt @@ -0,0 +1,50 @@ +/* The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Johannes Rudolph. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Johannes Rudolph + */ + += C++ exceptions in native programs = + +This native api program/library uses C++-features like classes in many +places. This seems to work without problems so far. +It would be appropriate to use C++ exceptions as well. This won't +work. At least not with much effort. C++ exceptions are working +through the subtle mechanisms of Windows, the C++ compiler *and* the +runtime library working together. + +To use exception handling one has to enable the specific options in +the compiler. You can use this lines in your SOURCES to enable it: + +{{{ +USE_NATIVE_EH=1 +USE_RTTI=1 +}}} + +If we don't link a runtime library linking will error with unresolved +externals like __CxxFrameHandler and others. + +Since we can't use Win32 dlls in a native program we can't link +against the standard rt (msvcrt). So the right choice seems to be the +use of the staticly linkable runtime library libc. This does not work +either. Even libc contains uncountable references to functions defined +in kernel32 and user32. We cannot link to them, of course. + +So your choices are: + * reimplement C++ exception handling on top of the native (API) features + provided by Windows and the compiler + * use structured exception handling as documented by Microsoft, this + will not work in functions relying on automatic object deconstruction + * don't use exceptions at all (that was my choice) \ No newline at end of file diff --git a/windows/bootpgm/native/MAKEFILE b/windows/bootpgm/native/MAKEFILE new file mode 100644 index 00000000..9c985f57 --- /dev/null +++ b/windows/bootpgm/native/MAKEFILE @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/windows/bootpgm/native/SOURCES b/windows/bootpgm/native/SOURCES new file mode 100644 index 00000000..f0c287c1 --- /dev/null +++ b/windows/bootpgm/native/SOURCES @@ -0,0 +1,16 @@ +TARGETNAME=bootpgm +TARGETPATH=..\obj +TARGETTYPE=PROGRAM + +TARGETLIBS=\ + ..\obj\i386\common.lib\ + $(DDK_LIB_PATH)\ntdll.lib\ + $(DDK_LIB_PATH)\nt.lib +# $(DDK_LIB_PATH)\libcmt.lib +# $(DDK_LIB_PATH)\ntoskrnl.lib + + +INCLUDES=$(SDK_INC_PATH);$(DDK_INC_PATH);..\win32 + +SOURCES= native.cpp +#UMTYPE=nt \ No newline at end of file diff --git a/windows/bootpgm/native/native.cpp b/windows/bootpgm/native/native.cpp new file mode 100644 index 00000000..e595d7a9 --- /dev/null +++ b/windows/bootpgm/native/native.cpp @@ -0,0 +1,427 @@ +/* The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Johannes Rudolph. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Johannes Rudolph + */ + +#include "stdafx.h" +#include "io.h" +#include "main.h" + +#include "newnative.h" + +#include "registrybrowser.h" + +#include +#include + +char keys[]={0,0,'1','2','3','4','5','6','7','8','9','0','ß','´',8/*Backspace*/ //0-14 + ,0/*tab*/,'q','w','e','r','t','z','u','i','o','p','ü','+','\n'/*return*/ //15-28 + ,0/*strg*/,'a','s','d','f','g','h','j','k','l','ö','ä','^',0/*left shift*/,'#' //29-43 + ,'y','x','c','v','b','n','m',',','.','-',0/*right shift*/ //44-54 + ,'*'/*num*/,0/*left alt*/,' ',0/*caps lock*/}; //55-58 + +char shiftkeys[]={0,0,'!','\"','§','$','%','&','/','(',')','=','?','`',0/*Backspace*/ //0-14 + ,0/*tab*/,'Q','W','E','R','T','Z','U','I','O','P','Ü','*','\n'/*return*/ //15-28 + ,0/*strg*/,'A','S','D','F','G','H','J','K','L','Ö','Ä','°',0/*left shift*/,'\'' //29-43 + ,'Y','X','C','V','B','N','M',';',':','_',0/*right shift*/ //44-54 + ,'*'/*num*/,0/*left alt*/,' ',0/*caps lock*/}; +IO *myIO=0; + +void fatal(char *msg) +{ + if (myIO!=0) + myIO->println(msg); + + NtTerminateProcess( NtCurrentProcess(), 0 ); +} + +struct KeyboardState +{ + bool shiftDown; + bool altDown; + bool altGrDown; + KeyboardState():shiftDown(false),altDown(false),altGrDown(false) + {} +}; + +class NativeBootIO:public IO{ + HANDLE Heap; + HANDLE Keyboard; + HANDLE KeyboardEvent; + KeyboardState keyboardState; +private: + void createHeap() + { + RTL_HEAP_DEFINITION heapParams; + memset( &heapParams, 0, sizeof( RTL_HEAP_DEFINITION )); + heapParams.Length = sizeof( RTL_HEAP_DEFINITION ); + Heap = RtlCreateHeap( 2, 0, 0x100000, 0x1000, 0, &heapParams ); + } + void openKeyboard() + { + UNICODE_STRING UnicodeFilespec; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + IO_STATUS_BLOCK Iosb; + + RtlInitUnicodeString(&UnicodeFilespec, L"\\device\\KeyboardClass0"); + InitializeObjectAttributes(&ObjectAttributes, // ptr to structure + &UnicodeFilespec, // ptr to file spec + OBJ_CASE_INSENSITIVE, // attributes + NULL, // root directory handle + NULL ); // ptr to security descriptor + + Status = ZwCreateFile(&Keyboard, // returned file handle + (GENERIC_READ|SYNCHRONIZE|FILE_READ_ATTRIBUTES), // desired access + &ObjectAttributes, // ptr to object attributes + &Iosb, // ptr to I/O status block + 0, // allocation size + FILE_ATTRIBUTE_NORMAL, // file attributes + 0, // share access + FILE_OPEN, // create disposition + 1, // create options + NULL, // ptr to extended attributes + 0); // length of ea buffer + + if (Status!=STATUS_SUCCESS) + fatal("Fehler: Keyboardhandle konnte nicht geöffnet werden"); + + InitializeObjectAttributes(&ObjectAttributes, // ptr to structure + NULL, // ptr to file spec + 0, // attributes + NULL, // root directory handle + NULL ); // ptr to security descriptor + Status=NtCreateEvent(&KeyboardEvent,EVENT_ALL_ACCESS,&ObjectAttributes,SynchronizationEvent,FALSE); + + if (Status!=STATUS_SUCCESS) + fatal("Fehler: Keyboardevent konnte nicht erstellt werden"); + } + void updateKeyboardStatus(KEYBOARD_INPUT_DATA &kid) + { + if (((kid.MakeCode==42)||(kid.MakeCode==54))&&(kid.Flags&KEY_E0)==0&&(kid.Flags&KEY_E1)==0) + keyboardState.shiftDown=!(kid.Flags&KEY_BREAK); + } + void printkid(KEYBOARD_INPUT_DATA &kid) + { + static char *buffer=(char*)malloc(100); + + int keyMake=kid.Flags&KEY_MAKE; + int keyBreak=kid.Flags&KEY_BREAK; + int e0=kid.Flags&KEY_E0; + int e1=kid.Flags&KEY_E1; + _snprintf(buffer,99,"Key: Code: %d\tMake: %d\tBreak: %d\te0: %d\te1: %d",kid.MakeCode,keyMake,keyBreak,e0,e1); + println(buffer); + } + +public: + NativeBootIO() + { + createHeap(); + openKeyboard(); + } + ~NativeBootIO() + { + //RtlDestroyHeap() + } + void handleCharEcho(char ch,char *buffer,unsigned int length) + { + char b[2]; + b[0]=ch; + b[1]=0; + if (ch==8) + { + println(""); + buffer[length]=0; + print("> "); + print(buffer); + } + else + print(b); + } + char getChar() + { + debugout("getChar startet"); + KEYBOARD_INPUT_DATA kid; + + int chr=0; + + do + { + NTSTATUS Status=waitForKeyboardInput(0,&kid); + if (Status!=STATUS_SUCCESS) + { + //_snprintf(buffer,99,"Fehler beim Tastaturlesen: 0x%x",Status); + println("Fehler beim Tastaturlesen"); + debugout("Fehler beim Tastatur lesen"); + } + else + { + debugout("Taste empfangen"); + + updateKeyboardStatus(kid); + + if (((kid.Flags&KEY_BREAK)==0)&&kid.MakeCode<58&&kid.MakeCode>0) + if (keyboardState.shiftDown) + chr=shiftkeys[kid.MakeCode]; + else + chr=keys[kid.MakeCode]; + else + chr=0; + } + } + while(chr==0); + debugout("getChar Ende"); + + return (char)chr; + } + void *malloc(unsigned int size) + { + return RtlAllocateHeap( Heap, 0, size); + } + void free(void *buffer) + { + RtlFreeHeap(Heap,0,buffer); + } + void internalPrint(char *buffer) + { + UNICODE_STRING UnicodeFilespec=getUnicodeString(buffer); + + NtDisplayString(&UnicodeFilespec); + } + char *getVersion() + { + return "Native Boot IO Revision: $Rev$"; + } + + NTSTATUS waitForKeyboardInput(__int64 time,KEYBOARD_INPUT_DATA *kid) + { + LARGE_INTEGER bo; + LARGE_INTEGER litime; + NTSTATUS Status; + IO_STATUS_BLOCK Iosb; + + bo.HighPart=0; + bo.LowPart=0; + + debugout("wFKI: vor ZwReadFile"); + + Status=ZwReadFile(Keyboard, + KeyboardEvent,0,0,&Iosb,kid,sizeof(KEYBOARD_INPUT_DATA),&bo,NULL); + + debugout("wFKI: nach ZwReadFile"); + + PLARGE_INTEGER pli=NULL; + + if (time!=0) + pli=(PLARGE_INTEGER)&time; + + if (Status==STATUS_PENDING) + { + debugout("wFKI: vor WaitFor..."); + + Status=NtWaitForMultipleObjects(1,&KeyboardEvent,1,1,pli); + + debugout("wFKI: nach WaitFor..."); + + if (Status!=STATUS_SUCCESS) + { + NtCancelIoFile(Keyboard,&Iosb); + return Status; + } + } + return STATUS_SUCCESS; + } + void printKeyboardData(KEYBOARD_INPUT_DATA kid) + { + char buffer[100]; + int keyMake=kid.Flags&KEY_MAKE; + int keyBreak=kid.Flags&KEY_BREAK; + int e0=kid.Flags&KEY_E0; + int e1=kid.Flags&KEY_E1; + _snprintf(buffer,99,"Key: Code: %d\tMake: %d\tBreak: %d\te0: %d\te1: %d\n",kid.MakeCode,keyMake,keyBreak,e0,e1); + debugout(buffer); + } + void testKeyboard() + { + KEYBOARD_INPUT_DATA kid; + kid.MakeCode=0; + char buffer[100]; + while(kid.MakeCode!=1) + { + NTSTATUS Status=waitForKeyboardInput(0,&kid); + if (Status!=STATUS_SUCCESS) + { + _snprintf(buffer,99,"Fehler beim Tastaturlesen: 0x%x",Status); + println(buffer); + } + else + { + printKeyboardData(kid); + } + } + println("Keyboardtest beendet"); + } + void resetKeyboard() + { + debugout("Clearing Event"); + NtClearEvent(KeyboardEvent); + } +}; + +extern "C" +int __cdecl _purecall() +{ + DbgBreakPoint(); + return 0; +} + +void debugBreak(IO &io,char *args) +{ + DbgBreakPoint(); +} + +void setCompnameFromFile(IO &io,char *args); +void setComputerNameCmd(IO &io,char *args); + +void myitoa(int i,char *buffer) +{ + int length=0; + if (i==0) + { + buffer[0]='0'; + length=1; + } + else + { + char buffer2[20]; + while (i>0) + { + buffer2[length]='0'+i%10; + i/=10; + length++; + } + for (i=0;i0) + if (keys[kid.MakeCode]==key) + { + io.debugout("Key pressed !!!"); + return true; + } + else + io.debugout("Wrong key pressed"); + else + io.printKeyboardData(kid); + + return false; +} + +bool startupWithKeyInner(NativeBootIO &io,int maxtime,char key) //maxtime in seconds +{ + io.print("System starting up: "); + + for (int i=maxtime;i>=0;i--) + { + char buffer[2]; + myitoa(i,buffer); + io.print(buffer); + io.print(" "); + + if (keyPressedInTime(io,-3333000,key)) + return true; + else + io.print("."); + + if (keyPressedInTime(io,-3333000,key)) + return true; + else + io.print("."); + + if (keyPressedInTime(io,-3333000,key)) + return true; + else + io.print(" "); + } + return false; +} +void clearKeyboardPipe(NativeBootIO &io) +{ + io.debugout("Starting clearKeyboardPipe"); + io.resetKeyboard(); + KEYBOARD_INPUT_DATA kid; + while (io.waitForKeyboardInput(-1,&kid)==STATUS_SUCCESS); + io.resetKeyboard(); + io.debugout("Ending clearKeyboardPipe"); + + +} +bool startupWithKey(NativeBootIO &io,int maxtime,char key) //maxtime in seconds +{ + bool res=startupWithKeyInner(io,maxtime,key); + io.println(" "); + clearKeyboardPipe(io); + return res; +} + +void register_experimental_cmds(Main &main); + +extern "C" void NtProcessStartup(::PPEB peb ) +{ + NativeBootIO io; + myIO=&io; + + UNICODE_STRING &cmdLine = peb->ProcessParameters->CommandLine; + + char **arguments; + int argc; + arguments=split_args(io,cmdLine.Buffer,cmdLine.Length/2,&argc); + + Main main(io,argc,arguments); + RegistryBrowser reg(main); + + main.addCommand("break",debugBreak); + main.addCommand("setComputerNameFromFile",setCompnameFromFile); + main.addCommand("setComputerName",setComputerNameCmd); + + register_experimental_cmds(main); + + main.showSplashScreen(); + +#ifdef INTERACTIVE + if (startupWithKey(io,2,'v')) + main.rpl(); + else +#endif + setCompnameFromFile(io,0); + + NtTerminateProcess( NtCurrentProcess(), 0 ); +} \ No newline at end of file diff --git a/windows/bootpgm/native/newnative.h b/windows/bootpgm/native/newnative.h new file mode 100644 index 00000000..59f1067d --- /dev/null +++ b/windows/bootpgm/native/newnative.h @@ -0,0 +1,322 @@ +/* The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Johannes Rudolph. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Johannes Rudolph + * Tomasz Nowak + * + * Most of this content comes from http://undocumented.ntinternals.net/ + * This page and the information used is written by + * Tomasz Nowak + * There is an .chm version in ../doc/ntundoc.chm + * The license presented on the page sounds: + * + * + * LICENSE CONDITIONS + * This software and / or documentation is provided at no cost + * and can be redistributed freely, in its entirety or in parts, + * as long as the Copyright notice and author's name are included. + * You are hereby permited to use, view, read, copy, print, publish, + * redistribute and modify this software and / or documentation, + * under conditions described herein. + * This software / documentation is provided to you "as is" without + * warranty of any kind. By using this material you accept all of the + * related risks and all direct and indirect consequences, including + * potential data loss and hardware damage. + * If you do not agree to these license conditions, please do not use + * our software and / or documentation. + * + */ + + + +#pragma once + +extern "C"{ +#define PPVOID void** +#define BYTE char + + /* I mostly copied this structures from the source above. + * I removed parts which would introduce spurious dependencies. + * + */ + typedef struct _RTL_DRIVE_LETTER_CURDIR { + USHORT Flags; + USHORT Length; + ULONG TimeStamp; + UNICODE_STRING DosPath; + } RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR; + + typedef struct _RTL_USER_PROCESS_PARAMETERS { + ULONG MaximumLength; + ULONG Length; + ULONG Flags; + ULONG DebugFlags; + PVOID ConsoleHandle; + ULONG ConsoleFlags; + HANDLE StdInputHandle; + HANDLE StdOutputHandle; + HANDLE StdErrorHandle; + UNICODE_STRING CurrentDirectoryPath; + HANDLE CurrentDirectoryHandle; + UNICODE_STRING DllPath; + UNICODE_STRING ImagePathName; + UNICODE_STRING CommandLine; + PVOID Environment; + ULONG StartingPositionLeft; + ULONG StartingPositionTop; + ULONG Width; + ULONG Height; + ULONG CharWidth; + ULONG CharHeight; + ULONG ConsoleTextAttributes; + ULONG WindowFlags; + ULONG ShowWindowFlags; + UNICODE_STRING WindowTitle; + UNICODE_STRING DesktopName; + UNICODE_STRING ShellInfo; + UNICODE_STRING RuntimeData; + RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20]; + } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; + + typedef struct _PEB { + BOOLEAN InheritedAddressSpace; + BOOLEAN ReadImageFileExecOptions; + BOOLEAN BeingDebugged; + BOOLEAN Spare; + HANDLE Mutant; + PVOID ImageBaseAddress; + PVOID/*PPEB_LDR_DATA*/ LoaderData; + PRTL_USER_PROCESS_PARAMETERS ProcessParameters; + PVOID SubSystemData; + PVOID ProcessHeap; + PVOID FastPebLock; + PVOID/*PPEBLOCKROUTINE*/FastPebLockRoutine; + PVOID/*PPEBLOCKROUTINE*/FastPebUnlockRoutine; + ULONG EnvironmentUpdateCount; + PPVOID KernelCallbackTable; + PVOID EventLogSection; + PVOID EventLog; + PVOID/*PPEB_FREE_BLOCK*/FreeList; + ULONG TlsExpansionCounter; + PVOID TlsBitmap; + ULONG TlsBitmapBits[0x2]; + PVOID ReadOnlySharedMemoryBase; + PVOID ReadOnlySharedMemoryHeap; + PPVOID ReadOnlyStaticServerData; + PVOID AnsiCodePageData; + PVOID OemCodePageData; + PVOID UnicodeCaseTableData; + ULONG NumberOfProcessors; + ULONG NtGlobalFlag; + BYTE Spare2[0x4]; + LARGE_INTEGER CriticalSectionTimeout; + ULONG HeapSegmentReserve; + ULONG HeapSegmentCommit; + ULONG HeapDeCommitTotalFreeThreshold; + ULONG HeapDeCommitFreeBlockThreshold; + ULONG NumberOfHeaps; + ULONG MaximumNumberOfHeaps; + PPVOID *ProcessHeaps; + PVOID GdiSharedHandleTable; + PVOID ProcessStarterHelper; + PVOID GdiDCAttributeList; + PVOID LoaderLock; + ULONG OSMajorVersion; + ULONG OSMinorVersion; + ULONG OSBuildNumber; + ULONG OSPlatformId; + ULONG ImageSubSystem; + ULONG ImageSubSystemMajorVersion; + ULONG ImageSubSystemMinorVersion; + ULONG GdiHandleBuffer[0x22]; + ULONG PostProcessInitRoutine; + ULONG TlsExpansionBitmap; + BYTE TlsExpansionBitmapBits[0x80]; + ULONG SessionId; + } PEB, *PPEB; + + typedef struct _RTL_HEAP_DEFINITION { + ULONG Length; + ULONG Unknown[12]; + } RTL_HEAP_DEFINITION, *PRTL_HEAP_DEFINITION; + + NTSYSAPI + NTSTATUS + NTAPI + NtTerminateProcess( + /*IN*/ HANDLE ProcessHandle /*OPTIONAL*/, + /*IN*/ NTSTATUS ExitStatus ); + + NTSYSAPI + NTSTATUS + NTAPI + NtDisplayString( + /*IN*/ PUNICODE_STRING String ); + + NTSYSAPI + PVOID + NTAPI + RtlCreateHeap( + /*IN*/ ULONG Flags, + /*IN*/ PVOID Base /*OPTIONAL*/, + /*IN*/ ULONG Reserve /*OPTIONAL*/, + /*IN*/ ULONG Commit, + /*IN*/ BOOLEAN Lock /*OPTIONAL*/, + /*IN*/ PRTL_HEAP_DEFINITION RtlHeapParams /*OPTIONAL*/ ); + + NTSYSAPI + PVOID + NTAPI + RtlAllocateHeap( + /*IN*/ PVOID HeapHandle, + /*IN*/ ULONG Flags, + /*IN*/ ULONG Size ); + + NTSYSAPI + BOOLEAN + NTAPI + RtlFreeHeap( + /*IN*/ PVOID HeapHandle, + /*IN*/ ULONG Flags /*OPTIONAL*/, + /*IN*/ PVOID MemoryPointer ); + + NTSYSAPI NTSTATUS NTAPI NtCreateEvent(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,EVENT_TYPE,BOOLEAN); + NTSYSAPI NTSTATUS NTAPI NtWaitForMultipleObjects(ULONG handlecount,PHANDLE handles,int wait_type,BOOLEAN alertable,PLARGE_INTEGER timeout); + NTSYSAPI NTSTATUS NTAPI NtClearEvent(HANDLE Eventhandle); + NTSYSAPI NTSTATUS NTAPI NtCancelIoFile(HANDLE Filehandle, PIO_STATUS_BLOCK IoStatusBlock); + + typedef enum _OBJECT_INFORMATION_CLASS + { + ObjectBasicInformation, // Result is OBJECT_BASIC_INFORMATION structure + ObjectNameInformation, // Result is OBJECT_NAME_INFORMATION structure + ObjectTypeInformation, // Result is OBJECT_TYPE_INFORMATION structure + ObjectAllInformation, // Result is OBJECT_ALL_INFORMATION structure + ObjectDataInformation // Result is OBJECT_DATA_INFORMATION structure + + } OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS; + + NTSYSAPI + NTSTATUS + NTAPI + NtQueryObject( + HANDLE ObjectHandle, + OBJECT_INFORMATION_CLASS ObjectInformationClass, + PVOID ObjectInformation, + ULONG Length, + PULONG ResultLength ); + + typedef struct _OBJECT_BASIC_INFORMATION { + ULONG Attributes; + ACCESS_MASK GrantedAccess; + ULONG HandleCount; + ULONG ReferenceCount; + ULONG PagedPoolQuota; + ULONG NonPagedPoolQuota; + ULONG Unknown[3]; + ULONG NameInformationLength; + ULONG TypeInformationLength; + ULONG SecurityDescriptorLength; + LARGE_INTEGER CreateTime; + } OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION; + + NTSYSAPI + NTSTATUS + NTAPI + NtLoadKey( + POBJECT_ATTRIBUTES DestinationKeyName, + POBJECT_ATTRIBUTES HiveFileName ); + + NTSYSAPI + NTSTATUS + NTAPI + NtOpenProcessToken( + HANDLE ProcessHandle, + ACCESS_MASK DesiredAccess, + PHANDLE TokenHandle ); + + typedef struct _TOKEN_PRIVILEGES + { + ULONG count; + LUID_AND_ATTRIBUTES Privileges[1]; + } TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES; + + NTSYSAPI + NTSTATUS + NTAPI + NtAdjustPrivilegesToken( + HANDLE TokenHandle, + BOOLEAN DisableAllPrivileges, + PTOKEN_PRIVILEGES TokenPrivileges, + ULONG PreviousPrivilegesLength, + PTOKEN_PRIVILEGES PreviousPrivileges, + PULONG RequiredLength); + + NTSYSAPI + NTSTATUS + NTAPI + NtUnloadKey( + POBJECT_ATTRIBUTES DestinationKeyName ); + + NTSYSAPI + NTSTATUS + NTAPI + NtFlushKey( + HANDLE KeyHandle ); + + NTSYSAPI + NTSTATUS + NTAPI + NtSaveKey( + HANDLE KeyHandle, + HANDLE FileHandle ); + + NTSYSAPI + NTSTATUS + NTAPI + NtInitializeRegistry( + int flag); + + typedef enum _DEBUG_CONTROL_CODE { + DebugSysReadIoSpace = 14, + DebugSysWriteIoSpace = 15, + DebugSysReadMsr = 16, + DebugSysWriteMsr = 17, + DebugSysReadBusData = 18, + DebugSysWriteBusData = 19, + } DEBUG_CONTROL_CODE; + + NTSYSAPI + NTSTATUS + NTAPI + ZwSystemDebugControl( + DEBUG_CONTROL_CODE ControlCode, + PVOID InputBuffer, + ULONG InputBufferLength, + PVOID OutputBuffer, + ULONG OutputBufferLength, + PULONG ReturnLength + ); + + typedef struct _IO_STRUCT { + int IoAddr; // IN: Aligned to NumBytes,I/O address + int Reserved1; // Never accessed by the kernel + PVOID pBuffer; // IN (write) or OUT (read): Ptr to buffer + int NumBytes; // IN: # bytes to read/write. Only use 1, 2, or 4. + int Reserved4; // Must be 1 + int Reserved5; // Must be 0 + int Reserved6; // Must be 1 + int Reserved7; // Never accessed by the kernel + } IO_STRUCT; +} \ No newline at end of file diff --git a/windows/bootpgm/win32/Handle.cpp b/windows/bootpgm/win32/Handle.cpp new file mode 100644 index 00000000..f55f3316 --- /dev/null +++ b/windows/bootpgm/win32/Handle.cpp @@ -0,0 +1,293 @@ +#include "StdAfx.h" +#include "Handle.h" +#include "main.h" + +void debug(char *msg) +{ + mainSingleton->get_io().debugout(msg); +} + +void handle(ULONG status,char *file,char *line) +{ + if (status!=STATUS_SUCCESS) + { + char *buffer = new char[5000]; + sprintf(buffer,"Fehler in %s Zeile %s: 0x%X",file,line,status); + mainSingleton->get_io().println(buffer); + mainSingleton->get_io().readln(buffer,sizeof(buffer)); + } +} + +WinObject::~WinObject() +{ + if (valid()) + { + char buffer[500]; + debug((L"Closing Handle to '" + get_name() + L"'" ).chars(buffer,500)); + ULONG status = ZwClose(handle); + CHECKER(status) + } +} + +UnicodeString WinObject::get_name() +{ + OBJECT_BASIC_INFORMATION info; + ULONG status = NtQueryObject( + handle + ,ObjectBasicInformation + ,&info + ,sizeof(info) + ,0); + + CHECKER(status); + + int len=info.NameInformationLength; + + len = len==0? 500 : len; + + if (len>0) + { + OBJECT_NAME_INFORMATION *poni=reinterpret_cast(_alloca(len)); + status = NtQueryObject( + handle + ,ObjectNameInformation + ,poni + ,len + ,0); + + CHECKER(status); + + return UnicodeString::from_unicode(poni->Name); + } + else + return UnicodeString(L""); +} + +UnicodeString::UnicodeString(const wchar_t *chars) +{ + unsigned short len = (unsigned short)wcslen(chars); + wchar_t *buffer=new wchar_t[len]; + string.Length= len * sizeof(wchar_t); + string.Buffer=buffer; + string.MaximumLength=string.Length; + memcpy(buffer,chars,len*2); + + /*debug("UnicodeString created:"); + char buffer2[500]; + debug(this->chars(buffer2,500));*/ +} +UnicodeString::UnicodeString(const wchar_t *chars,unsigned int length) +{ + string.Length = (USHORT)length; + string.MaximumLength = (USHORT)length; + string.Buffer = new wchar_t[length/2]; + memcpy(string.Buffer,chars,length); +} +UnicodeString::UnicodeString(const char *chars) +{ + unsigned short l=(unsigned short)strlen(chars); + wchar_t *wcs=new wchar_t[l]; + mbstowcs(wcs,chars,l); + string.Length = l*2; + string.MaximumLength = l*2; + string.Buffer = wcs; +} +/*UnicodeString &UnicodeString::operator=(wchar_t *chars) +{ + char buffer[1000]; + _snprintf(buffer,1000,"UnicodeString = called old = %S, new = %S",string.Buffer,chars); + debug(buffer); + + unsigned short len= (unsigned short)wcslen(chars) * 2; + + if (len > string.MaximumLength) + { + delete string.Buffer; + string.Buffer = new wchar_t[len/2]; + string.MaximumLength = len; + } + + memcpy(string.Buffer,chars,len); + string.Length = len; + + return *this; +}*/ +UnicodeString::~UnicodeString() +{ + debug("UnicodeString deleted:"); + char buffer[500]; + debug(this->chars(buffer,500)); + + delete string.Buffer; +} +UnicodeString UnicodeString::operator+(UnicodeString&str2) +{ + UNICODE_STRING str; + + str.Length = 0; + str.MaximumLength = string.Length + str2.string.Length; + str.Buffer = new wchar_t[str.MaximumLength/2]; + + NT::RtlAppendUnicodeStringToString(&str,&string); + NT::RtlAppendUnicodeStringToString(&str,&str2.string); + + return UnicodeString(str); +} + +int RegKey::get_value(UnicodeString *path,PULONG type,void *buffer,int length) +{ + int len=length + sizeof(KEY_VALUE_PARTIAL_INFORMATION); + void *temp=_alloca(len); + ULONG read; + KEY_VALUE_PARTIAL_INFORMATION *pinfo = reinterpret_cast(temp); + ULONG status=ZwQueryValueKey( + handle + ,&path->unicode_string() + ,KeyValuePartialInformation + ,pinfo + ,len + ,&read); + + CHECKER(status) + + if (status!=STATUS_SUCCESS) + return 0; + + memcpy(buffer,pinfo->Data,pinfo->DataLength); + *type = pinfo->Type; + return pinfo->DataLength; +} + +void RegKey::set_value(UnicodeString *path,ULONG type,void *data,ULONG size) +{ + ULONG status = ZwSetValueKey( + handle + ,&path->unicode_string() + ,0 + ,type + ,data + ,size); + CHECKER(status) +} + +UnicodeString RegKey::get_string_value(UnicodeString *name) +{ + char buffer[500]; + ULONG type; + ULONG len=get_value(name,&type,buffer,sizeof(buffer)); + + if (type!=REG_SZ){ + debug("Only REG_SZ allowed in get_string_value"); + return (wchar_t*)0; + } + + wchar_t *value= reinterpret_cast(buffer); + value[min(sizeof(buffer)-1,len)] = 0; + return value; +} + +HANDLE RegKey::open_key(HANDLE parent,UnicodeString &path) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + + UnicodeString fullPath = UnicodeString(L"\\Registry\\") + path; + UnicodeString *pp = parent ? &path : &fullPath; + + InitializeObjectAttributes( + &ObjectAttributes, + const_cast(&pp->unicode_string()), + OBJ_CASE_INSENSITIVE, + parent, + NULL); + + HANDLE h; + ULONG Disposition; + ULONG status = ZwOpenKey( + &h, + KEY_ALL_ACCESS, + &ObjectAttributes); + + if (status == 0xC000034){ + IO &io=mainSingleton->get_io(); + io.print("Not found: "); + char buffer[1000]; + io.println(path.chars(buffer,sizeof(buffer))); + } + + return status == STATUS_SUCCESS? h : 0; +} + +void RegKey::flush() +{ + ULONG status=NtFlushKey(handle); + CHECKER(status); +} + +void RegKey::save_to(HANDLE fileHandle) +{ + ULONG status = NtSaveKey(handle,fileHandle); + CHECKER(status); +} + +void RegKey::print_subkeys(IO &io) +{ + ULONG status = STATUS_SUCCESS; + int i=0; + char buffer[1000]; + do + { + ULONG res; + KEY_BASIC_INFORMATION *info = reinterpret_cast(buffer); + status = ZwEnumerateKey( + handle + ,i + ,KeyBasicInformation + ,buffer + ,sizeof(buffer) + ,&res); + + if (status == STATUS_SUCCESS) + { + UnicodeString name(info->Name,info->NameLength); + io.println(name.chars(buffer,sizeof(buffer))); + } + + i++; + } while (status == STATUS_SUCCESS); +} +void RegKey::print_values(IO &io) +{ + ULONG status = STATUS_SUCCESS; + int i=0; + char buffer[1000]; + do + { + ULONG len; + status = ZwEnumerateValueKey( + handle + ,i + ,KeyValueBasicInformation + ,buffer + ,sizeof(buffer)-2 + ,&len); + + if (status==STATUS_SUCCESS) + { + KEY_VALUE_BASIC_INFORMATION *info = reinterpret_cast(buffer); + info->Name[info->NameLength/2] = 0; + char buf[100]; + _snprintf(buf,sizeof(buf),"%-30S | %-15s",info->Name,type_to_name(info->Type)); + io.println(buf); + } + + i++; + } while(status == STATUS_SUCCESS); +} +RegKey *RegKey::subkey(UnicodeString&name) +{ + HANDLE h = open_key(handle,name); + if (h) + return new RegKey(h); + else + return 0; +} diff --git a/windows/bootpgm/win32/Handle.h b/windows/bootpgm/win32/Handle.h new file mode 100644 index 00000000..14f65e57 --- /dev/null +++ b/windows/bootpgm/win32/Handle.h @@ -0,0 +1,90 @@ +#pragma once + +class IO; + +class UnicodeString +{ + NT::UNICODE_STRING string; + UnicodeString(UNICODE_STRING str):string(str){} +public: + UnicodeString(const wchar_t *chars); + UnicodeString(const wchar_t *chars,unsigned int length); + UnicodeString(const char *chars); + UNICODE_STRING& unicode_string(){return string;} + virtual ~UnicodeString(); + static UnicodeString& from_unicode(UNICODE_STRING str) + { + UNICODE_STRING str2 = str; + str2.Buffer = new wchar_t[str.Length/2]; + memcpy(str2.Buffer,str.Buffer,str.Length); + return *new UnicodeString(str2); + } + //UnicodeString& operator=(wchar_t *new_data); + //UnicodeString& operator=(UnicodeString &other); + char *chars(char *buffer,size_t len) + { + wcstombs(buffer,string.Buffer,min(len,(unsigned int)string.Length/2)); + buffer[min(len-1,(unsigned int)string.Length/2)]=0; + return buffer; + } + UnicodeString operator+(UnicodeString&str2); + UnicodeString operator+(wchar_t *ch) + { + return *this + UnicodeString(ch); + } + + friend UnicodeString operator+(wchar_t* ch,UnicodeString str) + { + return UnicodeString(ch) + str; + } +}; + +class WinObject +{ +protected: + const HANDLE handle; +public: + WinObject(HANDLE h):handle(h){} +public: + ~WinObject(); + UnicodeString get_name(); + HANDLE get_handle(){return handle;} + bool valid(){return handle != 0;} +}; + +class RegKey:public WinObject +{ +private: + static HANDLE open_key(HANDLE parent,UnicodeString &path); + RegKey(HANDLE h):WinObject(h){} +public: + RegKey(UnicodeString &path):WinObject(open_key(0,path)){} + RegKey(const wchar_t *path):WinObject(open_key(0,UnicodeString(path))){} + + int get_value(UnicodeString *path,PULONG type,void *buffer,int length); + UnicodeString get_string_value(UnicodeString *name); + void set_value(UnicodeString *path,ULONG type,void *data,ULONG size); + void flush(); + void save_to(HANDLE fileHandle); + + RegKey *subkey(UnicodeString&name); + + void print_subkeys(IO &io); + void print_values(IO &io); + static const char *type_to_name(ULONG type) + { + switch(type) + { + case REG_SZ: + return "String"; + case REG_EXPAND_SZ: + return "Expandable String"; + case REG_MULTI_SZ: + return "Multiline String"; + case REG_DWORD: + return "DWORD"; + default: + return "Unknown"; + } + } +}; diff --git a/windows/bootpgm/win32/IO.cpp b/windows/bootpgm/win32/IO.cpp new file mode 100644 index 00000000..9b31832b --- /dev/null +++ b/windows/bootpgm/win32/IO.cpp @@ -0,0 +1,136 @@ +/* The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Johannes Rudolph. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Johannes Rudolph + */ + +#include "StdAfx.h" +#include "IO.h" + +IO::IO(void):indent(0),current(0) +{ +} + +IO::~IO(void) +{ +} +void IO::print(char *buffer) +{ + if (current==0) + { + for (int i=0;i0) + { + curlength--; + handleCharEcho(curChar[0],buffer,curlength); + } + } + } + buffer[curlength-1]=0; + + debugout("readln beendet"); + //NT::DbgPrint("readln beendet\n"); +} +wchar_t *IO::char2wchar(char *buffer) +{ + unsigned int size=strlen(buffer)+1; + wchar_t *buffer2=(wchar_t*)malloc(sizeof(wchar_t)*size); + mbstowcs(buffer2,(char*)buffer,size); + buffer2[size-1]=0; + + return buffer2; +} +NT::UNICODE_STRING IO::getUnicodeString(char *buffer) +{ + wchar_t *buffer2=char2wchar(buffer); + + NT::UNICODE_STRING UnicodeFilespec; + RtlInitUnicodeString(&UnicodeFilespec, buffer2); + + return UnicodeFilespec; +} + +void IO::handleStatus(NT::NTSTATUS status,char *place,char *file,char *line,bool onlyWhenDebugging){ +#ifndef DEBUGGING + if (!onlyWhenDebugging) +#endif + if (status!=STATUS_SUCCESS) + { + print("[error]"); + print(file); + print("("); + print(line); + println("):"); + print("[error] Fehler: "); + println(place); + NT::DbgPrint("Fehler (Datei: %s \tZeile: %s): %s, %d\n",file,line,place,status); + } + else + { + print("[success] Erfolg: "); + println(place); + NT::DbgPrint("Erfolg: %s\n",place); + } +} +inline void IO::debugout(char *string) +{ +//#ifdef DEBUGGING + //print("[debug] "); + //println(string); + NT::DbgPrint("[bootpgm] %s\n",string); +//#endif +} + +void IO::setIndent(unsigned char indent) +{ + this->indent=indent; +} +unsigned char IO::getIndent() +{ + return indent; +} \ No newline at end of file diff --git a/windows/bootpgm/win32/IO.h b/windows/bootpgm/win32/IO.h new file mode 100644 index 00000000..575aef06 --- /dev/null +++ b/windows/bootpgm/win32/IO.h @@ -0,0 +1,102 @@ +/* The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Johannes Rudolph. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Johannes Rudolph + */ + +/* +File: IO.h +Declaration of IO and Indenter classes +*/ + +#pragma once + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) +#define CHECK_STATUS(status,name) io.handleStatus(status, #name,__FILE__ ,TOSTRING(__LINE__),true); +#define CHECK_STATUSA(status,name) io.handleStatus(status, #name,__FILE__ ,TOSTRING(__LINE__),false); + +#define CHECKER(status) ::handle(status, __FILE__ ,TOSTRING(__LINE__)); +void handle(ULONG status,char *file,char *line); + +/* +Class: IO +Interface for the main input/output functions, contains some helper functions +*/ +class IO +{ + unsigned char indent; + unsigned char current; +public: + /* + Method: getChar + has to be implemented by concrete controllers + + Returns: + one char per call from input device (keyboard) + */ + virtual char getChar()=0; + /* + Method: internalPrint + prints buffer to screen, must be implemented by concrete controllers + + Parameters: + buffer - null-terminated string to be printed to screen + */ + virtual void internalPrint(char *buffer)=0; + /* + Method: malloc + allocates memory of specified size, must be implemented by concrete controllers + + Parameters: + length - length of buffer to allocate + + Returns: + pointer to allocated memory + */ + virtual void*malloc(unsigned int length)=0; + virtual void free(void *buffer)=0; + virtual char *getVersion()=0; + virtual void handleCharEcho(char ch,char *buffer,unsigned int length)=0; + + IO(void); + ~IO(void); + + void print(char *buffer); + void println(char *buffer); + void readln(char *buffer,unsigned int length); + wchar_t *char2wchar(char *buffer); + NT::UNICODE_STRING getUnicodeString(char *buffer); + void handleStatus(NTSTATUS status, char *function, char *file, char *line,bool onlyWhenDebugging); + void debugout(char *string); + void setIndent(unsigned char indent); + unsigned char getIndent(); +}; + +class Indenter +{ + unsigned char original; + IO &io; +public: + Indenter(IO &pio):io(pio) + { + original=io.getIndent(); + io.setIndent(original+2); + } + ~Indenter() + { + io.setIndent(original); + } +}; \ No newline at end of file diff --git a/windows/bootpgm/win32/MAKEFILE b/windows/bootpgm/win32/MAKEFILE new file mode 100644 index 00000000..9c985f57 --- /dev/null +++ b/windows/bootpgm/win32/MAKEFILE @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/windows/bootpgm/win32/Main.cpp b/windows/bootpgm/win32/Main.cpp new file mode 100644 index 00000000..f23a70ec --- /dev/null +++ b/windows/bootpgm/win32/Main.cpp @@ -0,0 +1,220 @@ +/* The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Johannes Rudolph. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Johannes Rudolph + */ + +#include "StdAfx.h" +#include "Main.h" + +Main *mainSingleton=NULL; + +char **split_args(IO &io,wchar_t* cmdLine,int length,int *pargc) +{ + int argCount=0; + for (int i=0;i(&func); + (p->*f)(io,args); + } + else + func(io,args); +} + + +void Main::showCmds(IO &io,char *args) +{ + io.println("Available commands:"); + Indenter i(io); + for (int i=0;ihelp ? cmd->help : "No help entry available"); +} + +command *Main::findCommand(char *name) +{ + for(int i=0;i\nShow help entries for command if available"); + + if (mainSingleton!=NULL) + { + io.println("Error: Main may be instantiated only once"); + return; + } + else + { + mainSingleton=this; + } +} + +Main::~Main(void) +{ + mainSingleton=NULL; +} + +void Main::run() +{ + showSplashScreen(); + rpl(); +} +void Main::rpl() +{ + io.println("Starting RPL (Read-Print-Loop) Type \"exit\" to stop."); + + char buffer[100]; + buffer[0]=0; + + while (strcmp(buffer,"exit")!=0) + { + io.print("rpl> "); + io.readln(buffer,100); + + command *cmd=findCommand(buffer); + if (cmd) + cmd->invoke(io,buffer + strlen(cmd->name)); + else + io.println("Command not found"); + } + + io.println("Exiting RPL"); +} +void Main::showSplashScreen() +{ + io.println("Boot-time Computername Changer by Johannes Rudolph"); + io.println("v0.1"); + io.print("IO: "); + io.println(io.getVersion()); +} + +void Main::addCommand(char *name,invokeFunc func,char *desc,char *help,void*pObject) +{ + if (funcc>=maxFuncs) + { + io.println("Es kann kein neues Kommando hinzugefügt werden"); + return; + } + + command c; + c.func=func; + c.name=name; + c.description=desc; + c.help=help; + c.pObject=pObject; + + commands[funcc]=c; + + funcc++; +} + +void Main::addCommand(char *name,deleg dg,char *desc,char *help) +{ + addCommand(name,(invokeFunc)dg.func,desc,help,dg.object); +} + + +void* __cdecl operator new(size_t sz) { + IO& io=mainSingleton->get_io(); + void* m = io.malloc((unsigned int)sz); + + if(!m) + io.println("out of memory"); + + return m; +} + +void __cdecl operator delete(void* m) { + mainSingleton->get_io().free(m); +} diff --git a/windows/bootpgm/win32/Main.h b/windows/bootpgm/win32/Main.h new file mode 100644 index 00000000..bd0e1bab --- /dev/null +++ b/windows/bootpgm/win32/Main.h @@ -0,0 +1,90 @@ +/* The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Johannes Rudolph. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Johannes Rudolph + */ + +#pragma once +#include "io.h" + +typedef void (*invokeFunc)(IO &io,char *args); + +struct command{ + invokeFunc func; + void *pObject; + char *name; + char *description; + char *help; + void invoke(IO &io,char *args); +}; + +struct deleg +{ + void *func; + void *object; +}; + +// template to create a command delegate +template deleg make_dg(T *t,void(T::*func)(IO&,char*)) +{ + deleg dg; + dg.func = *(void**)&func; + dg.object = t; + return dg; +} + +class Main +{ + IO &io; + + int funcc; + static const int maxFuncs=50; + command commands[maxFuncs]; + + char** argv; + int argc; + + void help(IO &io,char *args); + void showCmds(IO &io,char *args); + void showArgs(IO &io,char *args); + + command *findCommand(char *name); +public: + Main(IO &io,int argc,char** argv); + void run(); + ~Main(void); + void rpl(); + void addCommand(char *name,invokeFunc func,char *desc=0,char *help=0,void *pObject=0); + void addCommand(char *name,deleg d,char *desc=0,char *help=0); + + void showSplashScreen(); + IO &get_io(){return io;} +private: + friend void showCmds(IO &io,char *args); + friend void showArgs(IO &io,char *args); + +public: + int getArgc() + { + return argc; + } + char **getArgs() + { + return argv; + } +}; + +extern Main *mainSingleton; +char **split_args(IO &io,wchar_t* cmdLine,int length,int *pargc); \ No newline at end of file diff --git a/windows/bootpgm/win32/RegistryBrowser.cpp b/windows/bootpgm/win32/RegistryBrowser.cpp new file mode 100644 index 00000000..9254f8e8 --- /dev/null +++ b/windows/bootpgm/win32/RegistryBrowser.cpp @@ -0,0 +1,71 @@ +#include "StdAfx.h" +#include "RegistryBrowser.h" +#include "io.h" +#include "main.h" +#include "handle.h" + +RegKey *RegistryBrowser::get_current_key() +{ + if (!current) + current = new RegKey(L""); + + return current; +} + +void RegistryBrowser::lk(IO &io,char *args) +{ + get_current_key()->print_subkeys(io); +} +void RegistryBrowser::lv(IO &io,char *args) +{ + get_current_key()->print_values(io); +} + +void RegistryBrowser::tk(IO &io,char *args) +{ + char buffer[1000]; + io.println(get_current_key()->get_name().chars(buffer,sizeof(buffer))); +} + +void RegistryBrowser::ck(IO &io,char *args) +{ + if (*args==0) + { + if (current) delete current; + current = 0; + return; + } + + UnicodeString name(&args[1]); + RegKey *key=get_current_key()->subkey(name); + if (key) + { + if (current) delete current; + current = key; + } + else + io.println("Key not found"); +} + +RegistryBrowser::RegistryBrowser(Main &main) : current(0) +{ + main.addCommand("lk",make_dg(this,&RegistryBrowser::lk) + ,"List subkeys" + ,"Usage: lk\nList all subkeys of the current key"); + main.addCommand("lv",make_dg(this,&RegistryBrowser::lv) + ,"List values" + ,"Usage: lv\nList the names of all values of the current key with their types"); + main.addCommand("ck",make_dg(this,&RegistryBrowser::ck) + ,"Change current registry key" + ,"Usage: ck []\nGo into the subkey if specified or else to the root of the registry"); + main.addCommand("tk",make_dg(this,&RegistryBrowser::tk) + ,"Show information about current key" + ,"Usage: tk\nShow information about the current key (*t*his *k*ey)"); +} + +RegistryBrowser::~RegistryBrowser(void) +{ + if (current) + delete current; + current = 0; +} diff --git a/windows/bootpgm/win32/RegistryBrowser.h b/windows/bootpgm/win32/RegistryBrowser.h new file mode 100644 index 00000000..57424320 --- /dev/null +++ b/windows/bootpgm/win32/RegistryBrowser.h @@ -0,0 +1,19 @@ +#pragma once + +class RegKey; +class IO; +class Main; + +class RegistryBrowser +{ + RegKey *current; + RegKey *get_current_key(); +public: + RegistryBrowser(Main &m); + ~RegistryBrowser(void); + + void lk(IO &io,char *args); + void lv(IO &io,char *args); + void ck(IO &io,char *args); + void tk(IO &io,char *args); +}; diff --git a/windows/bootpgm/win32/SOURCES b/windows/bootpgm/win32/SOURCES new file mode 100644 index 00000000..8bf55002 --- /dev/null +++ b/windows/bootpgm/win32/SOURCES @@ -0,0 +1,25 @@ +TARGETNAME=common +TARGETPATH=../obj +TARGETTYPE=LIBRARY +#USE_NATIVE_EH= +#USE_RTTI= +#TARGETTYPE=PROGRAM + +TARGETLIBS=$(DDK_LIB_PATH)\ntdll.lib +# $(DDK_LIB_PATH)\libc.lib +# $(DDK_LIB_PATH)\msvcrt.lib + + +INCLUDES=$(SDK_INC_PATH);$(DDK_INC_PATH); +SOURCES=io.cpp \ + main.cpp \ + stdafx.cpp \ + computername.cpp \ + tests.cpp \ + registrybrowser.cpp \ + experimental.cpp \ + account.cpp \ + handle.cpp + +#UMTYPE=console +#UMBASE=0x400000 diff --git a/windows/bootpgm/win32/account.cpp b/windows/bootpgm/win32/account.cpp new file mode 100644 index 00000000..24a3c32e --- /dev/null +++ b/windows/bootpgm/win32/account.cpp @@ -0,0 +1,60 @@ +#include "stdafx.h" + +#include "account.h" + +void *get_entry(char *data,unsigned int cEntries,unsigned int index,unsigned int *length) +{ + data_entry *entries = reinterpret_cast(data); + if (length != 0) + *length = entries[index].length; + + return data + sizeof(data_entry) * cEntries + entries[index].position; +} + +void *get_V_entry(char *data,unsigned int index, unsigned int *length) +{ + return get_entry(data,17,index,length); +} + +entry *read_entries(char *data,unsigned int cEntries) +{ + data_entry *entries = reinterpret_cast(data); + entry *fixed = new entry[cEntries]; + for(unsigned int i=0;i(buffer); + + int pos = 0; + + for(unsigned int i=0;i + */ + +/* +File: computername.cpp +functions to change the computer name in the Windows registry +*/ + +#include "stdafx.h" +#include "io.h" +#include "main.h" + +WCHAR KeyNameBuffer[] = L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ComputerName"; +WCHAR KeyNameBuffer2[] = L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName"; +WCHAR Tcpip[] = L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"; +WCHAR ComputerNameBuffer[] = L"ComputerName"; + +/* +Function: setRegistryValue + +Parameters: +io: reference to -Controller +*/ +void setRegistryValue(IO &io,WCHAR *keyName,WCHAR *valueName,WCHAR *value) +{ + Indenter i(io); + UNICODE_STRING KeyName, ValueName; + HANDLE SoftwareKeyHandle; + ULONG Status; + OBJECT_ATTRIBUTES ObjectAttributes; + ULONG Disposition; + + //io.print("Schreibe Registry-Key "); + + //DbgBreakPoint(); + // + // Open the Software key + // + NT::RtlInitUnicodeString(&KeyName,keyName); + InitializeObjectAttributes( + &ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = ZwCreateKey( + &SoftwareKeyHandle, + KEY_ALL_ACCESS, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + &Disposition); + + CHECK_STATUS(Status,Öffnen des Schlüssels) + + NT::RtlInitUnicodeString(&ValueName,valueName); + + Status = ZwSetValueKey( + SoftwareKeyHandle, + &ValueName, + 0, + REG_SZ, + value, + (wcslen( value )+1) * sizeof(WCHAR)); + + CHECK_STATUSA(Status,Setzen des Schlüssels); + + Status = ZwClose(SoftwareKeyHandle); + + CHECK_STATUS(Status,Schließen des Schlüssels); +} + +/* +Function: setComputerName +sets the computer name in the registry to the specified one + +Parameters: +io - reference to the -Controller +computerName - the designated computer name as UNICODE string +*/ +void setComputerName(IO &io,WCHAR *computerName) +{ + Indenter i(io); + io.println("Setze Computernamen "); + setRegistryValue(io,KeyNameBuffer,ComputerNameBuffer,computerName); + setRegistryValue(io,KeyNameBuffer2,ComputerNameBuffer,computerName); + setRegistryValue(io,Tcpip,L"Hostname",computerName); + setRegistryValue(io,Tcpip,L"NV Hostname",computerName); +} +/* +Function: setComputerNameCmd +command line command for setting the computer name manually + +Parameters: +io - -Controller +args - command line argument string +*/ +void setComputerNameCmd(IO &io,char *args) +{ + Indenter i(io); + if (strlen(args)<2) + { + io.println("Syntax: setComputerName "); + return; + } + io.print("Setting Computer Name to: "); + io.println(args+1); + setComputerName(io,io.char2wchar(args+1)); +} + +#define RETURN_NULL_IF_STATUS_UNSUCCESSFULL if (Status!=STATUS_SUCCESS) return 0; + +/* +Constant: whitespaces +defines whitespace character group, each char of this array +designates one white space character +*/ +const char whitespaces[]=" \t\n\x0B\f\r"; + +/* +Function: isWhitespace +Helper function for regexp parser. Tests if c is white space. + +Parameters: +c - character to test + +Returns: +true if character is white space as defined in +*/ +bool isWhitespace(char c) +{ + for (int i=0;i='A'&&c<='Z'; +} +bool isDigit(char c) +{ + return c>='0'&&c<='9'; +} +bool isSmallLetter(char c) +{ + return c>='a'&&c<='z'; +} + +bool isWordCharacter(char c) +{ + return isDigit(c)||isCapitalLetter(c)||isSmallLetter(c)||c=='-'; +} +bool char_matcher(char c,char d) +{ + return c==d; +} +//const char pattern[]="Computername:\\s+(\\w+)"; +/* +Constant: pattern +regular expression pattern which defines the place in a file +to read the computer name from. + +The computer name will be the match for the first bracketed expression. + +Example: +: * +*/ +const char pattern[]=" to find a match in the buffer + +Parameters: +io - -Controller +buffer - source buffer +length - length of source buffer + +Returns: +a string containing the match or 0 otherwise +*/ +char *parseComputerNameFile(IO &io,char *buffer,unsigned int length) +{ + int patternpos=0; + int capture_start=-1; + int capture_end=-1; + void *matcher=0; + char lastData=0; + for (unsigned int i=0;i0) + i--; + patternpos++; + continue; + default: + lastData=pattern[patternpos]; + matcher=char_matcher; + break; + } + + matched=false; + if (lastData!=0) + matched=((bool(*)(char,char))matcher)(buffer[i],lastData); + else + matched=((bool(*)(char))matcher)(buffer[i]); + + if (matched) + patternpos++; + else + patternpos=0; + } + if (pattern[patternpos]==')') + capture_end=length; + + if (capture_start!=-1&&capture_end!=-1) + { + int matchlength=capture_end-capture_start; + char *returnBuffer=(char*)io.malloc(matchlength+1); + memcpy(returnBuffer,buffer+capture_start,matchlength); + returnBuffer[matchlength]=0; + return returnBuffer; + } + else + return 0; +} + +void testMatcher(IO &io,char *args) +{ + char string[]="Computername: "; + char *return0=parseComputerNameFile(io,string,sizeof(string)); +} + +/* +Function: readComputerNameFromFile +reads the computer name from the specified file, uses to +find computer name in it + +Parameters: +io - -Controller +fileName - reads computer name from this file + +Returns: +UNICODE string containing the new computer name, 0 in case of error or if +the name couldn't be found +*/ +wchar_t *readComputerNameFromFile(IO &io,wchar_t *fileName) +{ + Indenter i(io); + NTSTATUS Status; + UNICODE_STRING UnicodeFilespec; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE FileHandle; + IO_STATUS_BLOCK Iosb; + char *buffer; + PWCHAR buffer2; + ULONG converted; + + RtlInitUnicodeString(&UnicodeFilespec,fileName); + + InitializeObjectAttributes( + &ObjectAttributes, // ptr to structure + &UnicodeFilespec, // ptr to file spec + OBJ_CASE_INSENSITIVE, // attributes + NULL, // root directory handle + NULL ); // ptr to security descriptor + + Status = ZwCreateFile( + &FileHandle, // returned file handle + (GENERIC_READ | SYNCHRONIZE), // desired access + &ObjectAttributes, // ptr to object attributes + &Iosb, // ptr to I/O status block + 0, // allocation size + FILE_ATTRIBUTE_NORMAL, // file attributes + 0, // share access + FILE_OPEN, // create disposition + FILE_SYNCHRONOUS_IO_NONALERT, // create options + NULL, // ptr to extended attributes + 0); // length of ea buffer + + CHECK_STATUSA(Status,Öffnen der Computernamensdatei) + RETURN_NULL_IF_STATUS_UNSUCCESSFULL + + buffer = (char*)io.malloc(256);//RtlAllocateHeap( Heap, 0, 256 ); + Status = ZwReadFile(FileHandle,0,NULL,NULL,&Iosb,buffer,256,0,NULL); + ((char*)buffer)[Iosb.Information]=0; + + CHECK_STATUSA(Status,Lesen des Computernamens); + RETURN_NULL_IF_STATUS_UNSUCCESSFULL + + io.print("Trying to parse file ... "); + char *parsed=parseComputerNameFile(io,buffer,Iosb.Information); + + if (parsed!=0) + { + io.print("successful: "); + io.println(parsed); + } + else + { + io.println("failed."); + io.free(buffer); + io.free(parsed); + return 0; + } + + buffer2 = (PWCHAR)io.malloc(500); + + mbstowcs(buffer2,(char*)parsed,strlen(parsed)); + + Status = ZwClose(FileHandle); + + CHECK_STATUS(Status,Schließen der Datei); + + io.free(buffer); + io.free(parsed); + + return buffer2; +} + +/* +Function: setCompnameFromFile +command line command to set computer name from file. + +Uses a list of files to find computer name. List consists of +command line parameters and hard coded *\\device\\floppy0\\compname.txt*. + +Tries to read each file and extract the computer name in the list till a +valid one is found. This is set as computer name afterwards. + +Parameters: +io - -Controller +args - command line +*/ +void setCompnameFromFile(IO &io,char *args) +{ + Indenter i(io); + int numFiles=mainSingleton->getArgc(); + char **valueNames=(char**)io.malloc(4*numFiles); + char **cmdargs=mainSingleton->getArgs(); + + io.print("Computername file pipe: "); + + for (int i=1;i + */ + +// stdafx.cpp : source file that includes just the standard includes +// usermode-registry.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/windows/bootpgm/win32/stdafx.h b/windows/bootpgm/win32/stdafx.h new file mode 100644 index 00000000..4450335a --- /dev/null +++ b/windows/bootpgm/win32/stdafx.h @@ -0,0 +1,50 @@ +/* The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Johannes Rudolph. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Johannes Rudolph + */ + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#endif +#include +#include +#include +#include +#include + +namespace NT { + extern "C" { +#ifndef _X86_ + #define _X86_ +#endif +#pragma warning(disable: 4005) +#include +#include +#pragma warning(default: 4005) + } +} + +using namespace NT; +#include "../native/newnative.h" + +// TODO: reference additional headers your program requires here diff --git a/windows/bootpgm/win32/usermode-registry.sln b/windows/bootpgm/win32/usermode-registry.sln new file mode 100644 index 00000000..a732e479 --- /dev/null +++ b/windows/bootpgm/win32/usermode-registry.sln @@ -0,0 +1,23 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual C++ Express 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "usermode-registry", "usermode-registry.vcproj", "{63B64315-1D50-4C6B-8A9D-69E44436FBF6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Library|Win32 = Library|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {63B64315-1D50-4C6B-8A9D-69E44436FBF6}.Debug|Win32.ActiveCfg = Debug|Win32 + {63B64315-1D50-4C6B-8A9D-69E44436FBF6}.Debug|Win32.Build.0 = Debug|Win32 + {63B64315-1D50-4C6B-8A9D-69E44436FBF6}.Library|Win32.ActiveCfg = Library|Win32 + {63B64315-1D50-4C6B-8A9D-69E44436FBF6}.Library|Win32.Build.0 = Library|Win32 + {63B64315-1D50-4C6B-8A9D-69E44436FBF6}.Release|Win32.ActiveCfg = Release|Win32 + {63B64315-1D50-4C6B-8A9D-69E44436FBF6}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/windows/bootpgm/win32/usermode-registry.vcproj b/windows/bootpgm/win32/usermode-registry.vcproj new file mode 100644 index 00000000..57a2e4e9 --- /dev/null +++ b/windows/bootpgm/win32/usermode-registry.vcproj @@ -0,0 +1,365 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/windows/bootpgm/win32/win32.cpp b/windows/bootpgm/win32/win32.cpp new file mode 100644 index 00000000..cc3999fe --- /dev/null +++ b/windows/bootpgm/win32/win32.cpp @@ -0,0 +1,92 @@ +/* The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * + * The Initial Developer of the Original Code is Johannes Rudolph. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Johannes Rudolph + */ + +#include "stdafx.h" +#include "io.h" +#include "main.h" +#include "registrybrowser.h" + +class UsermodeIO:public IO{ +public: + char getChar() + { + return getchar(); + } + void internalPrint(char *buffer) + { + printf(buffer); + } + char *getVersion() + { + return "Usermode IO"; + } + void *malloc(unsigned int length) + { + return ::malloc(length); + } + void free(void *buffer) + { + ::free(buffer); + } + void handleCharEcho(char ch,char *buffer,unsigned int length) + { + // no echo necessary because getchar() echos + } +}; + +void splitArgs(IO &io,char *args){ + if (strlen(args)==0) + return; + + int argc; + UNICODE_STRING str; + wchar_t *wstr; + char buffer[100]; + wstr=(wchar_t*)buffer; + mbstowcs(wstr,args,50); + NT::RtlInitUnicodeString(&str,wstr); + str.Length-=2; + char **argv=split_args(io,str.Buffer,str.Length/2,&argc); + for (int i=0;i