Compartilhar via


Por dentro dos Aplicativos Nativos

Mark Russinovich Publicado em: 1 de novembro de 2006

Introdução

Se você tem alguma familiaridade com a arquitetura do NT, provavelmente sabe que a API que os aplicativos Win32 utilizam não é a API "real" do NT. Os ambientes operacionais do NT, que incluem POSIX, OS/2 e Win32, conversam com seus aplicativos clientes através de suas próprias APIs, mas conversam com o NT usando a API "nativa" do NT. A API nativa é, em sua maior parte, não documentada, com apenas cerca de 25 das suas 250 funções descritas no Kit de Drivers de Dispositivos do Windows NT.

O que a maioria das pessoas não sabe, entretanto, é que existem aplicativos "nativos" no NT que não são clientes de nenhum dos ambientes operacionais. Esses programas falam a API nativa do NT e não podem usar APIs de ambientes operacionais como o Win32. Por que esses programas seriam necessários?" Qualquer programa que precise ser executado antes de o subsistema Win32 ser iniciado (por volta do tempo em que a caixa de logon aparece) deve ser um aplicativo nativo. O exemplo mais visível de um aplicativo nativo é o programa "autochk" que executa chkdsk na inicialização do Blue Screen (é o programa que imprime o "."'s na tela). Naturalmente, o servidor do ambiente operacional Win32, CSRSS.EXE (Subsistema de Runtime do Cliente-Servidor), também deve ser um aplicativo nativo.

Neste artigo, descreverei como os aplicativos nativos são criados e como funcionam.

Como o Autochk é executado

O Autochk é executado entre o tempo em que os drivers de inicialização do NT e de início do sistema são carregados e quando a paginação é ativada. Nesse ponto da sequência de inicialização, o Gerenciador de Sessão (smss.exe) está preparando o ambiente de modo de usuário do NT e nenhum outro programa está ativo. O valor HKLM\System\CurrentControlSet\Control\Session Manager\BootExecute, um MULTI_SZ, contém os nomes e os argumentos dos programas que são executados pelo Gerenciador de Sessão e é onde o Autochk é especificado. Aqui está o que você normalmente encontrará se examinar esse valor, em que "Autochk" é passado "*" como argumento:

Autocheck Autochk *

O Gerenciador de Sessão procura no diretório <winnt>\system32 os executáveis listados nesse valor. Quando o Autochk é executado, não existem arquivos abertos, de modo que o Autochk pode abrir qualquer volume em modo bruto, inclusive a unidade de inicialização, e manipular suas estruturas de dados no disco. Isso não seria possível em nenhum momento posterior.

Criando Aplicativos Nativos

A Microsoft não documenta isso, mas o utilitário NT DDK Build sabe como criar aplicativos nativos (e provavelmente é usado para compilar o Autochk). Você especifica informações em um arquivo FONTES que define o aplicativo, da mesma forma que seria feito com os drivers de dispositivo. Porém, em vez de indicar à Compilação que você quer um driver, você diz a ele que deseja um aplicativo nativo no arquivo SOURCES, assim:

TARGETTYPE=PROGRAM

O utilitário Build usa um makefile padrão para orientá-lo, \ddk\inc\makefile.def, que procura uma biblioteca de tempo de execução chamada nt.lib ao compilar aplicativos nativos. Infelizmente, a Microsoft não envia esse arquivo com o DDK (ele está incluído no DDK do Server 2003, mas suspeito que, se você criar um link com essa versão, seu aplicativo nativo não será executado no XP ou no Windows 2000). No entanto, você pode contornar esse problema incluindo uma linha no makefile.def que substitui a seleção do nt.lib especificando a biblioteca de runtime do Visual C++, msvcrt.lib

Se você executar o Build no ambiente "Checked Build" do DDK, ele produzirá um aplicativo nativo com informações completas de depuração em %BASEDIR%\lib%CPU%\Checked (por exemplo, c:\ddk\lib\i386\checked\native.exe) e, se você o invocar no ambiente "Free Build", uma versão de lançamento do programa será colocada em %BASEDIR%\lib%CPU%\Free. Esses são os mesmos locais nos quais as imagens do driver de dispositivo são colocadas pelo Build.

Os aplicativos nativos têm extensões de arquivo ".exe", mas não é possível executá-los como os .exe do Win32. Se você tentar, receberá a mensagem:

O aplicativo não pode ser executado no modo Windows NT.

Dentro de um Aplicativo Nativo

Em vez de winmain ou main, o ponto de entrada para aplicativos nativos é NtProcessStartup. Também diferentemente dos outros pontos de entrada do Win32, os aplicativos nativos precisam acessar uma estrutura de dados passada como seu único parâmetro para localizar os argumentos da linha de comando.

A maior parte do ambiente de runtime de um aplicativo nativo é fornecida pela NTDLL.DLL, a biblioteca de exportação da API nativa do NT. Os aplicativos nativos devem criar seu próprio heap para alocar o armazenamento usando RtlCreateHeap, uma função da NTDLL. A memória é alocada de um heap com RtlAllocateHeap e liberada com RtlFreeHeap. Se um aplicativo nativo desejar imprimir algo na tela, ele deverá usar a função NtDisplayString, que produzirá a Tela Azul de inicialização.

Os aplicativos nativos não retornam simplesmente da função de inicialização como os programas Win32, pois não existe um código de runtime para o qual retornar. Em vez disso, eles precisam ser encerrados chamando NtProcessTerminate.

O runtime da NTDLL consiste em centenas de funções que permitem que os aplicativos nativos executem a E/S de arquivos, interajam com drivers de dispositivos e realizem comunicações entre processos. Infelizmente, como afirmei anteriormente, a grande maioria dessas funções não está documentada.