À l'intérieur des applications natives

Mark Russinovich Publié le 1er novembre 2006

Introduction

Si vous êtes familiarisé avec l'architecture de NT, vous savez probablement que l'API utilisée par les applications Win32 n'est pas la "vraie" API NT. Les environnements d'exploitation de NT, qui incluent POSIX, OS/2 et Win32, communiquent avec leurs applications clientes via leurs propres API, mais communiquent avec NT à l'aide de l'API "native" de NT. L'API native est pour la plupart non documentée, avec seulement environ 25 de ses 250 fonctions décrites dans le kit de pilote de périphérique Windows NT.

Ce que la plupart des gens ignorent, cependant, c'est qu'il existe des applications "natives" sur NT qui ne sont clientes d'aucun des environnements d'exploitation. Ces programmes parlent l'API NT native et ne peuvent pas utiliser les API d'environnement d'exploitation telles que Win32. Pourquoi de tels programmes seraient-ils nécessaires ? Tout programme qui doit s'exécuter avant le démarrage du sous-système Win32 (au moment où la boîte de connexion apparaît) doit être une application native. L’exemple le plus visible d’une application native est le programme « autochk » qui exécute chkdsk lors de l’initialisation Écran bleu (c’est le programme qui affiche les « . » à l’écran). Naturellement, le serveur de l'environnement d'exploitation Win32, CSRSS.EXE (Client-Server Runtime Subsystem), doit également être une application native.

Dans cet article, je vais décrire comment les applications natives sont construites et comment elles fonctionnent.

Comment Autochk est-il exécuté

Autochk s'exécute entre le moment où les pilotes de démarrage et de démarrage du système de NT sont chargés et le moment où la pagination est activée. À ce stade de la séquence de démarrage, Session Manager (smss.exe) lance l'environnement en mode utilisateur de NT et aucun autre programme n'est actif. La valeur HKLM\System\CurrentControlSet\Control\Session Manager\BootExecute, un MULTI_SZ, contient les noms et les arguments des programmes qui sont exécutés par Session Manager, et c'est là que Autochk est spécifié. Voici ce que vous trouverez généralement si vous regardez cette valeur, où "Autochk" est passé "*" comme argument :

Autocheck Autochk *

Session Manager recherche dans le répertoire <winnt>\system32 les exécutables répertoriés dans cette valeur. Lorsque Autochk s'exécute, aucun fichier n'est ouvert. Autochk peut donc ouvrir n'importe quel volume en mode brut, y compris le lecteur de démarrage, et manipuler ses structures de données sur disque. Cela ne serait plus possible ultérieurement.

Création d'applications natives

Microsoft ne le documente pas, mais l'utilitaire NT DDK Build sait comment créer des applications natives (et il est probablement utilisé pour compiler Autochk). Vous spécifiez des informations dans un fichier SOURCES qui définissent l'application, de la même manière que pour les pilotes de périphérique. Cependant, au lieu d’indiquer à Build que vous voulez un pilote, vous lui dites que vous voulez une application native dans le fichier SOURCES comme ceci :

TARGETTYPE=PROGRAM

L'utilitaire Build utilise un makefile standard pour le guider, \ddk\inc\makefile.def, qui recherche une bibliothèque d'exécution nommée nt.lib lors de la compilation d'applications natives. Malheureusement, Microsoft ne fournit pas ce fichier avec le DDK (il est inclus dans le DDK Server 2003, mais je soupçonne que si vous créez un lien avec cette version, votre application native ne fonctionnera pas sous XP ou Windows 2000). Cependant, vous pouvez contourner ce problème en incluant une ligne dans makefile.def qui remplace la sélection de nt.lib en spécifiant la bibliothèque d'exécution de Visual C++, msvcrt.lib

Si vous exécutez Build sous l'environnement "Checked Build" du DDK, il produira une application native avec des informations de débogage complètes sous %BASEDIR%\lib%CPU%\Checked (par exemple, c:\ddk\lib\i386\checked\native.exe) , et si vous l'invoquez dans l'environnement "Free Build", une version finale du programme se retrouvera dans %BASEDIR%\lib%CPU%\Free. Ce sont les mêmes endroits où les images de pilote de périphérique sont placées par Build.

Les applications natives ont des extensions de fichier ".exe" mais vous ne pouvez pas les exécuter comme les .exe de Win32. Si vous essayez, vous obtiendrez le message :

L'application ne peut pas être exécutée en mode Windows NT.

Dans une application native

Au lieu de winmain ou main, le point d'entrée des applications natives est NtProcessStartup. Contrairement aux autres points d'entrée Win32, les applications natives doivent accéder à une structure de données transmise comme seul paramètre pour localiser les arguments de ligne de commande.

La majorité de l'environnement d'exécution d'une application native est fournie par NTDLL.DLL, la bibliothèque d'exportation d'API native de NT. Les applications natives doivent créer leur propre tas à partir duquel allouer le stockage à l'aide de RtlCreateHeap, une fonction NTDLL. La mémoire est allouée à partir d'un tas avec RtlAllocateHeap et libérée avec RtlFreeHeap. Si une application native souhaite imprimer quelque chose à l'écran, elle doit utiliser la fonction NtDisplayString, qui affichera l'écran bleu d'initialisation.

Les applications natives ne reviennent pas simplement de leur fonction de démarrage comme les programmes Win32, car il n'y a pas de code d'exécution auquel revenir. Au lieu de cela, ils doivent se terminer en appelant NtProcessTerminate.

Le runtime NTDLL se compose de centaines de fonctions qui permettent aux applications natives d'effectuer des E/S de fichiers, d'interagir avec des pilotes de périphériques et d'effectuer des communications interprocessus. Malheureusement, comme je l'ai dit plus tôt, la grande majorité de ces fonctions ne sont pas documentées.