Sign in Join
Wiki copytemporary

Target NativeNT: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11*(Windows only)*
22
33This target allows to compile applications for the basic Windows NT kernel interface. This includes usermode applications und kernelmode device drivers.
44
55## Reasons for this port
66
77Windows NT operating systems (Windows NT 3.5 up to Windows 7) are based on a design that allows running different environments (called "environment subsystem") that user applications interact with.
88
99Examples are
1010
1111- the infamous Win32 subsystem (which provides the WinAPI)
1212- the POSIX / Interix subsystem (included as SUA in Windows Vista/7 Ultimate and Enterprise)
1313- OS/2 subsystem (dropped in Windows 2000)
1414
1515Those subsystems don't use the usual WinAPI, but the API of the NT kernel itself which is exposed through ntdll.dll to user space. Also the device drivers that run on a Windows NT system don't use the WinAPI, but the API provided by **ntoskrnl.exe** and **hal.dll**.
1616
1717As the Win32/64 targets link to WinAPI I saw no better way than to start a new target which supports the kernel API, but thanks to the very common structure of Win32/64 and NativeNT (same binary format, many kernel32 functions are similar to ntdll ones) the implementation of this port is rather (!) easy.
1818
1919## Supported systems
2020
2121In theory, user mode applications and device drivers can support all Windows NT versions from Windows NT 4 or even 3.51 on, but the only tested systems are currently:
2222
2323- Windows 2000 (Windows NT 5.0)
2424- [ReactOS](http://www.ReactOS.org/) (equivalent to Windows 2003 or Windows NT 5.2, see also [[ReactOS]])
2525
2626The supported versions depend on the used functions. For a rather complete list and the supported kernels see [here](http://jedi-apilib.sourceforge.net/native/NativeList.html).
2727
2828Also the only supported processor architecture is currently i386. A port to x86_64 (Windows XP and newer) is planned in the near future. Also once the ARM and PPC ports of ReactOS are mature enough (e. g. kernel itself and early user mode is running) I plan to make ports for them.
2929
3030Note: Device drivers for WinCE systems are NOT possible with this port, as that system has a different kernel structure.
3131
3232## Building the compiler
3333
3434Currently only a cross compiler is available. To build it you need a version of Free Pascal newer than revision 14568, e.g. FPC 2.6 or later.
3535
3636On Linux and similar:
3737
3838``` bash
3939cd $YourFPCDir
4040cd compiler
4141make
4242cp ppc386 $WhereYouWantTheCompiler
4343cd ../utils/fpcm
4444make
4545cp fpcmake $WhereYouWantFPCMake
4646```
4747
4848On Windows (assuming you use an SVN checkout/source directory):
4949
5050- go to directory where you checked out FPC
5151- open cmd.exe (e. g. Start -\> Run -\> Write "cmd" -\> OK )
5252- navigate to your FPC directory
5353
5454```dos
5555cd compiler
5656make
5757cp ppc386.exe %WhereYouWantTheCompiler%
5858cd ..\utils\fpcm
5959make
6060cp fpcmake.exe %WhereYouWantFPCMake%
6161```
6262
6363Notes:
6464
6565- on Windows, you need to have the GNU make utility in your PATH (e.g. the one provided with Lazarus) or use its absolute path
6666- on Windows and Linux/*nix you need to have FPC in your PATH or supply it to make with "FPC=path/to/fpc/binary"
6767- you do not need to do the copy steps, it's mainly useful if you want to replace your installed (trunk) compiler
6868- compiling the fpcmake utility is needed!
6969
7070## Building the RTL
7171
7272Now you can compile the RTL
7373
7474- for usermode
7575
7676``` bash
7777make FPC=$YourNewPPC386Binary OS_TARGET=nativent
7878```
7979
8080- for kernelmode
8181
8282``` bash
8383make FPC=$YourNewPPC386Binary OS_TARGET=nativent OPT="-dKMODE"
8484```
8585
8686\$YourNewPPC386Binary is "../../compiler/ppc386" when you didn't copy it to another directory.
8787
8888The compiled units will be in "../units/i386-nativent" (relative from nativent directory).
8989
9090Note:
9191
9292- the define for kernel mode is needed, because the differences between kernel and user mode are rather huge, but I also didn't want to maintain two targets for this (also a normal user doesn't compile the RTL very often)
9393- if you want to have both RTLs compile the kernel mode one first and copy the units to an "i386-nativent-kmode" directory (for example)
9494
9595## Usermode Hello World
9696
9797### Building
9898
9999If you're experienced enough you can modify your fpc.cfg to include the NativeNT units (TODO), but for now I only use compiler command line switches.
100100
101101``` pascal
102102program helloworld;
103103
104104uses
105105 // as WriteLn is not supported, yet, we need to
106106 // use the functions provided by the kernel directly
107107 NDK, NDKUtils;
108108
109109var
110110 ntstr: TNtUnicodeString;
111111 interval: TLargeInteger;
112112begin
113113 ShortStrToNtStr('Hello World!'#13#10, ntstr);
114114 NtDisplayString(@ntstr);
115115 FreeMem(ntstr.buffer);
116116
117117 // wait 3 seconds
118118 interval.QuadPart := - 3000 * 10000;
119119 NtDelayExecution(@interval);
120120end.
121121```
122122
123123Compile like this
124124
125125``` bash
126126$YourNewPPC386 -n -Tnativent -Fu$PathToUserModeRTL helloworld.pas
127127```
128128
129129You should now have a helloworld.exe file in your current directory.
130130
131131Note: Your anti virus may complain about this new executable, but it is clean!
132132
133133### Running
134134
135135**Important: Do NOT test this on a production machine (I mean it!). I'm not responsible for any damage to your computer.**
136136
137137Copy the new executable to your test machine (e.g. a VM) into the system32 directory of your Windows/ReactOS installation (e.g. C:\WINNT\system32 up to Windows 2000, C:\Windows\system32 from Windows XP on, C:\ReactOS\system32 on ReactOS). You might want to backup the registry file system32\config\SYSTEM (e.g. not needed if you use QEMU with an QCow2 base image). Open regedit (Start -\> Run -\> Write "regedit" -\> OK) and navigate to
138138
139-`HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager`
139+```text
140+HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager
141+```
140142
141143and edit the BootExecute value (you should see a "autochk" in there). Add this after the "AutoCheck" entry:
142144
143-`HelloWorld helloworld`
145+```text
146+HelloWorld helloworld
147+```
144148
145149First "HelloWorld" is a custom name and second one is the name of the executable inside the system32 directory. You can optionally pass arguments after "helloworld" like "*" in "AutoCheck" entry, but you need to parse them manually as ParamStr/-Count isn't implemented yet.
146150
147151Now restart the machine. You should see a "Hello World!" message in the top left corner of the screen after the boot screen. If you see a Bluescreen: well, I hope you didn't use a production machine.
148152
149153## Kernelmode Hello World
150154
151155### Building
152156
153157The note about configuration in user mode applies here, too.
154158
155159``` pascal
156160library helloworld; // this is important - do not try a "program" here
157161
158162// tell FPC that we want to compile a kernel mode application
159163// (NEEDS a RTL that was compiled with KMODE)
160164{$apptype native}
161165
162166uses
163167 // for entry point types and debug output
164168 DDK;
165169
166170// this method is called once our driver is unloaded
167171procedure DriverUnload(aObject: PDriverObject); stdcall;
168172begin
169173 DbgPrint('Unloading driver');
170174end;
171175
172176// during the entry point the variables DriverObject and
173177// RegistryPath are valid
174178begin
175179 DbgPrint('Hello World!');
176180
177181 // we need to setup the unload routine or the driver will
178182 // only be unloaded on shutdown!
179183 DriverObject^.DriverUnload := @DriverUnload;
180184end.
181185```
182186
183187Compile like this:
184188
185189``` bash
186190$YourNewPPC386 -n -Tnativent -Fu$PathToKernelModeRTL -ohelloworld.sys helloworld.pas
187191```
188192
189193The naming convention for drivers is ".sys", so we change the extention from .dll to .sys.
190194
191195### Running
192196
193197**Note:** As long as you set the driver to "start on demand", instead of "start on boot" or "start automatically" you *might* do this on a production machine, but I don't recommend it.
194198
195199To see the debug messages you need a tool for Windows like [DebugView](http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx) (I didn't test this on ReactOS, though) which needs to be started before the driver.
196200
197201Now copy the driver to the system32\drivers directory on your test machine.
198202
199203To run a driver you need to install it as a service (yes, drivers are regarded as "services" - this might be a heritage of the Mach architecture of Windows NT). I've created a tool which uses the Service Control Manager API to do this, but until I've uploaded it somewhere you need to install it manually:
200204
201205- open regedit
202206- navigate to HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
203207- create a new key and give it a unique name (e.g. "helloworld")
204208- add the following values in there:
205209
206210| Name | Type | Value |
207211|--------------|-----------|---------------------------------|
208212| ErrorControl | DWORD | 0x00000001 |
209213| ImagePath | EXPAND_SZ | system32\drivers\helloworld.sys |
210214| Start | DWORD | 0x00000003 |
211215| Type | DWORD | 0x00000001 |
212216
213217Note: You might not be able to create an expandable string value (EXPAND_SZ) in Windows (you can in ReactOS and Vista for certain), so you need to trick by exporting another driver entry and modifying that or you write a Pascal tool which creates those entries.
214218
215219Before you can start the driver you need to generate a PE checksum for it (as far as I know Windows checks the PE checksum at least for drivers). You need a tool which can generate a PE checksum or you can write your own one (there are some examples on the net). Also you can wait until I've uploaded my DriverHelper tool which can do this, too.
216220
217221After you've created the checksum, you can finally start the driver:
218222
219223- open cmd.exe
220224- type "net start helloworld" (the name of the KEY you created)
221225- now you should get a "Hello World!" message inside DebugView (or whatever application you use for viewing debug output)
222226- type "net stop helloworld" to unload the driver (you should get another message in your debuging application)
223227
224228Note: If you get a BSOD you can simply restart and everything will be fine until you start the driver again.
225229
226230## Driver signing
227231
228232A 64-bit kernel mode driver needs to be signed. And it may be that on Windows 10+ a 32-bit driver also needs to be signed. You can during development use a local certificate for that as per the DDK documentation on MSDN.
229233
23023432-bit drivers below or equal to platform Windows 7 are known to work.
231235
232236---
233237*From the Free Pascal wiki, page "Target NativeNT", as it stood on 2022-10-22 after a change by Alextp, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
234238Category: Windows

Back to history