Dentro das aplicações nativas

Mark Russinovich Publicado: 1 de novembro de 2006

Introdução

Se tem alguma familiaridade com a arquitetura do NT, provavelmente sabe que a API que as aplicações Win32 usam não é a "verdadeira" API do NT. Os ambientes operativos do NT, que incluem POSIX, OS/2 e Win32, comunicam com as suas aplicações cliente através das suas próprias APIs, mas comunicam com o NT usando a API "nativa" do NT. A API nativa é maioritariamente não documentada, com apenas cerca de 25 das suas 250 funções descritas no Windows NT Device Driver Kit.

O que a maioria das pessoas não sabe, no entanto, é que existem aplicações "nativas" no NT que não são clientes de nenhum dos ambientes operativos. Estes programas falam a API nativa do NT e não conseguem usar APIs do ambiente operativo como o Win32. Porque seriam necessários tais programas?" Qualquer programa que tenha de correr antes do início do subsistema Win32 (por volta da altura em que a caixa de login aparece) deve ser uma aplicação nativa. O exemplo mais visível de uma aplicação nativa é o programa "autochk", que executa o CHKDSK durante o ecrã azul de inicialização (é o programa que imprime os pontos (.) no ecrã). Naturalmente, o servidor do ambiente operativo Win32, CSRSS.EXE (Client-Server Subsistema de Runtime), também deve ser uma aplicação nativa.

Neste artigo, vou descrever como as aplicações nativas são construídas e como funcionam.

Como é executado o Autochk

O Autochk é executado entre o momento em que os drivers de arranque e arranque do sistema do NT são carregados e quando a paginação está ativada. Nesta fase da sequência de arranque, o Gestor de Sessões (smss.exe) está a iniciar o ambiente em modo de utilizador do NT e não existem outros programas em execução. 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 Session Manager e é aí que o Autochk é especificado. Eis o que normalmente encontrará se observar este valor, em que "Autochk" recebe "*" como argumento:

Autocheck Autochk *

O Gestor de Sessões procura no <diretório winnt>\system32 os executáveis listados neste valor. Quando o Autochk é executado, não há ficheiros abertos, pelo que o Autochk pode abrir qualquer volume em modo bruto, incluindo a unidade de arranque, e manipular as suas estruturas de dados no disco. Isto não seria possível mais tarde.

Construção de Aplicações Nativas

A Microsoft não documenta isso, mas a utilidade NT DDK Build sabe como criar aplicações nativas (e provavelmente é usada para compilar o Autochk). Especificas informação num ficheiro SOURCES que define a aplicação, tal como seria feito para drivers de dispositivos. No entanto, em vez de indicares ao Build que queres um driver, dizes que queres uma aplicação nativa no ficheiro SOURCES, desta forma:

TARGETTYPE=PROGRAM

A utilidade Build utiliza um makefile padrão para o orientar, \ddk\inc\makefile.def, que procura uma biblioteca em tempo de execução chamada nt.lib ao compilar aplicações nativas. Infelizmente, a Microsoft não inclui este ficheiro com o DDK (está incluído no DDK do Server 2003, mas suspeito que, se ligares a essa versão, a tua aplicação nativa não correrá no XP ou Windows 2000). No entanto, podes contornar este problema incluindo uma linha no makefile.def que sobrepõe a seleção do nt.lib especificando a biblioteca de runtime do Visual C++, msvcrt.lib

Se executares o Build no ambiente "Checked Build" do DDK, ele gerará uma aplicação nativa com informação completa de depuração em %BASEDIR%\lib%CPU%\Checked (ex.: c:\ddk\lib\i386\checked\native.exe), e se a invocares no ambiente "Free Build", uma versão release do programa acabará em %BASEDIR%\lib%CPU%\Free. Estes são os mesmos locais onde as imagens dos drivers de dispositivo são colocadas pelo Build.

As aplicações nativas têm extensões de ficheiro ".exe", mas não podes executá-las como no Win32 .exe. Se tentar, vai perceber a mensagem:

A aplicação não pode ser executada em modo Windows NT.

Dentro de uma Aplicação Nativa

Em vez de winmain ou main, o ponto de entrada para aplicações nativas é NtProcessStartup. Também ao contrário dos outros pontos de entrada Win32, as aplicações nativas devem aceder a uma estrutura de dados passada como único parâmetro para localizar argumentos na linha de comandos.

A maior parte do ambiente de execução de uma aplicação nativa é fornecida pela NTDLL.DLL, a biblioteca nativa de exportação de APIs do NT. As aplicações nativas devem criar o seu próprio heap a partir do qual alocar armazenamento usando o RtlCreateHeap, uma função NTDLL. A memória é alocada num heap com RtlAllocateHeap e libertada com RtlFreeHeap. Se uma aplicação nativa quiser imprimir algo no ecrã, deve usar a função NtDisplayString, que irá exportar para o Blue Screen de inicialização.

As aplicações nativas não regressam simplesmente da função de arranque como os programas Win32, pois não há código de execução para regressar. Em vez disso, têm de se terminar a si próprios chamando NtProcessTerminate.

O runtime NTDLL consiste em centenas de funções que permitem a aplicações nativas realizar I/O de ficheiros, interagir com controladores de dispositivos e realizar comunicações entre processos. Infelizmente, como referi anteriormente, a grande maioria destas funções é não documentada.