Inuti inbyggda program

Mark Russinovich Publicerad: 1 november 2006

Introduktion

Om du är bekant med NT:s arkitektur är du förmodligen medveten om att det API som Win32-program använder inte är det "riktiga" NT-API:et. NT:s driftsmiljöer, som inkluderar POSIX, OS/2 och Win32, pratar med sina klientprogram via sina egna API:er, men pratar med NT med hjälp av NT:s "interna" API. Det interna API:et är mestadels odokumenterad, med endast cirka 25 av dess 250 funktioner som beskrivs i Windows NT Device Driver Kit.

Vad de flesta inte vet är dock att "interna" program finns på NT som inte är klienter i någon av driftsmiljöerna. De här programmen talar om det interna NT-API:et och kan inte använda API:er för driftsmiljö som Win32. Varför skulle sådana program behövas" Alla program som måste köras innan Win32-undersystemet startas (ungefär när inloggningsrutan visas) måste vara ett internt program. Det mest synliga exemplet på ett internt program är "autochk"-programmet som kör chkdsk under initieringen Blue Screen (det är programmet som skriver ut "". s på skärmen). Naturligtvis måste Win32-operativsystemmiljöservern, CSRSS.EXE (Client-Server Runtime Subsystem), också vara ett internt program.

I den här artikeln ska jag beskriva hur inbyggda program skapas och hur de fungerar.

Hur kör autochk köras

Autochk körs mellan den tid då NT:s start- och systemstartdrivrutiner läses in och när växling är aktiverat. Nu i startsekvensen får Sessionshanteraren (smss.exe) NT:s användarlägesmiljö från marken och inga andra program är aktiva. Värdet HKLM\System\CurrentControlSet\Control\Session Manager\BootExecute , en MULTI_SZ, innehåller namn och argument för program som körs av Sessionshanteraren och är där Autochk anges. Här är vad du vanligtvis hittar om du tittar på det här värdet, där "Autochk" skickas "*" som ett argument:

Autocheck Autochk *

Sessionshanteraren söker i <katalogen winnt>\system32 efter de körbara filer som anges i det här värdet. När Autochk körs finns det inga öppna filer så Autochk kan öppna valfri volym i raw-läge, inklusive startenheten, och ändra dess datastrukturer på disken. Detta skulle inte vara möjligt vid något senare tillfälle.

Skapa inbyggda program

Microsoft dokumenterar det inte, men NT DDK Build-verktyget vet hur man gör inbyggda program (och det används förmodligen för att kompilera Autochk). Du anger information i en SOURCES-fil som definierar programmet, på samma sätt som för enhetsdrivrutiner. Men i stället för att ange för Build att du vill ha en drivrutin, säger du att du vill ha ett inbyggt program i SOURCES-filen så här:

TARGETTYPE=PROGRAM

Verktyget Build använder en standard makefile för att vägleda den, \ddk\inc\makefile.def, som söker efter ett körningsbibliotek med namnet nt.lib när inbyggda program kompileras. Tyvärr skickar Inte Microsoft den här filen med DDK (ingår i Server 2003 DDK, men jag misstänker att om du länkar till den versionen kommer ditt interna program inte att köras på XP eller Windows 2000). Du kan dock kringgå det här problemet genom att inkludera en rad i makefile.def som åsidosätter valet av nt.lib genom att ange Visual C++:s runtime-bibliotek, msvcrt.lib

Om du kör Build under DDK:ns "Checked Build"-miljö skapas ett internt program med fullständig felsökningsinformation under %BASEDIR%\lib%CPU%\Checked (t.ex. c:\ddk\lib\i386\checked\native.exe), och om du anropar det i miljön "Free Build" kommer en versionsversion av programmet att hamna i %BASEDIR%\lib%CPU%\Free. Det här är samma platser där enhetsdrivrutinsbilder placeras av Build.

Interna program har filnamnstillägg för ".exe", men du kan inte köra dem som Win32 .exe. Om du försöker får du meddelandet:

Det går inte att köra programmet i Windows NT-läge.

Inuti ett internt program

I stället för winmain eller main är startpunkten för inbyggda program NtProcessStartup. Till skillnad från de andra Win32-startpunkterna måste interna program nå till en datastruktur som skickas som den enda parametern för att hitta kommandoradsargument.

Majoriteten av ett internt programs körningsmiljö tillhandahålls av NTDLL.DLL, NT:s interna API-exportbibliotek. Interna program måste skapa en egen heap som du kan allokera lagring från med hjälp av RtlCreateHeap, en NTDLL-funktion. Minnet allokeras från en heap med RtlAllocateHeap och frigörs med RtlFreeHeap. Om ett internt program vill skriva ut något på skärmen måste det använda funktionen NtDisplayString, som kommer att mata ut till initieringen Blue Screen.

Interna program returnerar inte bara från sin startfunktion som Win32-program, eftersom det inte finns någon körningskod att återgå till. I stället måste de avsluta sig själva genom att anropa NtProcessTerminate.

NTDLL-körningen består av hundratals funktioner som gör att interna program kan utföra fil-I/O, interagera med enhetsdrivrutiner och utföra kommunikation mellan processer. Tyvärr, som jag sade tidigare, är de allra flesta av dessa funktioner odokumenterade.