пятница, 26 октября 2007 г.

Приоритет процесса при запуске

Раз уж зашла речь о приоритетах, то сразу скажу о возможности установки приоритета процесса при запуске средствами Windows.

Как известно Windows по умолчанию запускает процессы с приоритетом Normal, который можно повысить или понизить во время выполнения, к примеру, из TaskManager.
Если же мы хотим установить базовый приоритет при старте приложения, то можно воспользоваться командой start:

cmd /c start /[приоритет] application.exe

где, [приоритет] = LOW, BELOWNORMAL, NORMAL, ABOVENORMAL, HIGH, REALTIME

Что бы избавить себя от раздражающих задержек при одновременном просмотре фильма и игры, для игры был создан ярлык следующего содержания:

%windir%\system32\cmd.exe /c start /low d:\games\lineage2\system\la2.exe

Приоритет процесса в vmware

К своему стыду вынужден признаться: уже сколько пользуюсь vmware, а до сих пор не знал что в ней можно указать низкий приоритет, дабы не ощущать паралельные тормоза на машине.

В общем если вдруг так случилось что кто то ещё не знает об этой фиче, то даю наводку: главное меню -> VM -> Settings... -> Options -> Advanced.
Там можно найти настройки приоритета для активного и неактивного случая.

четверг, 25 октября 2007 г.

XML в ядре

Существует замечательная мультиплатформеная библиотека для работы с XML именуемая The Expat XML Parser.Так вот оказалось что малой кровью её можно заставить работать и в ядре. Ниже я приведу шаги которые были применены для сборки отладочной версии статической библиотеки с драйвером.

Изменение кода Expat проекта в Visual Studio:
Нам нужно переопределить используемые CRTшные функции отсутсвующие в ядре. Это:
free
malloc
realloc
assert
memcmp

Для примера это можно сделать включив в проект файл со следующим содержанием:
#define _X86_
#include

void __cdecl free(void * _Memory)
{
if( _Memory )
ExFreePoolWithTag(_Memory, 'test');
}

void * __cdecl malloc( size_t _Size)
{
return (void*)ExAllocatePoolWithTag(NonPagedPool, _Size, 'test' );
}

void * __cdecl realloc( void * _Memory, size_t _NewSize)
{
if( _Memory )
ExFreePoolWithTag(_Memory, 'myma');
return (void*)ExAllocatePoolWithTag(NonPagedPool, _NewSize, 'test' );
}

int __cdecl memcmp(const void * _Buf1, const void * _Buf2, size_t _Size)
{
return (int)RtlCompareMemory( _Buf1, _Buf2, _Size );
}

void __cdecl assert( unsigned char something )
{

}

Кстати, для вышеприведенного кода нужно установить соглашение о вызове __stdcall. Это связано с тем что в прототипе
ExFreePoolWithTag это не указано явно.


Изменение настроек Expat проекта в Visual Studio:
1. C/C++ --> General --> Debug Information Format = Program Database (/Zi)
2. C/C++ --> CodeGeneration --> Basic Runtime Checks = Default
3. Подключить ntoskrnl.lib
4. Установить __stdcall для файла с переопределенными функциями (если используется ExFreePoolWithTag);

Код драйвера:
Если предполагается копмилировать статическую библиотеку (а это предполагается :) ), то нужно продефайнить:
#define XML_BUILDING_EXPAT 1

Ниже приведены заглушки которые можно реализовать (а можно пользоваться теми, что были переопределены выше):
..............
void * __cdecl MyMalloc(size_t size)
{
return ExAllocatePoolWithTag( NonPagedPool, size, '
test' );
}

void * __cdecl MyRealloc(void *ptr, size_t size)
{
if( ptr )
ExFreePoolWithTag(ptr, 'myma');
return ExAllocatePoolWithTag( NonPagedPool, size, '
test' );
}

void __cdecl MyFree(void *ptr)
{
if( ptr )
ExFreePoolWithTag(ptr, '
test');
}

NTSTATUS DriverEntry(
IN PDRIVER_OBJECT pDriverObject,
IN PUNICODE_STRING pusRegistryPath
)
{
XML_Memory_Handling_Suite memsuite;
...................

myMemSuite.malloc_fcn = (void *(__stdcall *)(size_t))&MyMalloc;
myMemSuite.realloc_fcn = (void *(__stdcall *)(void *,size_t))&MyRealloc;
myMemSuite.free_fcn = (void (__stdcall *)(void *))&MyFree;

parser = XML_ParserCreate_MM(NULL, &memsuite, NULL);
..........................
}

sources драйвера:
TARGETLIBS=XmlParser.lib

Пример библиотеки и вызывающего драйвера постараюсь выложить в ближайшее время.

Вот и всё. Вся эта морока с соглашениями о вызове нужна была что бы свести к минимуму вносимые изменения в код библиотеки.

Свежую версию Expat всегда можно найти на http://expat.sourceforge.net/

MAC адреса в Vista WFP (входящие пакеты)

Как известно в висте появилась чудесная и действительно удобная технология для анализа и редактирования IP трафика: WFP. Естественно, поскольку WFP охватывает только tcp/ip стэк (а это сетевой и транспортный уровень), то для работы с MAC адресом Microsoft предлагает поспользоваться старыми добрыми NDIS драйверами.

Но не всё так плохо в королевстве датском, оказывается что в случае с входящими пакетами на network inbound layer имеет смысл не делать оффсет на ip header, а взглянуть на 14 байт сразу перед ним. Там обнаруживается ethernet header для этого пакета, и что приятно обнаруживается всегда.

Парочка полезных инструментов в разработке драйверов.

Как оказалось для разработки и тестирования драйверов помимо WDK и Debugging tools существует целый ряд утилит, причем довольно приятные в использовании и в большинстве своём бесплатные. Всего за день уже настолько пристрастился к ним что даже не знаю как раньше обходился :).
Итак встречаем:
prefast - static analyze (поставляется вместе с WDK)
BullseyeCoverage - Run-Time analyze (хороша, хоть и не бесплатна. есть здесь http://www.bullseye.com/)
verifier - testing tool (отличная вещь, поставляется вместе с виндовз.)

How To configure Visual Studio 2005 for compiling drivers

As you should be know microsoft officially doesn`t support integration DDK with Visual Studio. So you can use Visual Studio editor (or any other editor) for make sources, but for compiling you should use the DDK build utility. Of course it is not very conveniently because you must always switch between editor and console window, but most terrible that developer spend much time for find lines with error in editor.

There are several ways to compile drivers with visual studio. Most of them you can find in nice Mark Roddy article "Windows Driver Build Methods and Tools" here: http://www.wd-3.com/archive/HowBuild.htm

Mark offers use some third party utilities. That`s good, but I will show more handly way (IMHO): how to configure and use Visual Studio for compiling drivers.


1. Setup Visual Studio 2005 (I guess it can be any other VS version)

2. Setup DDK (or WDK)

3. Add to VS pathes to DDK include files and libs.

4. Create new empty "Win32 project" and add source file (e.g. init.c).

5. Configure project properties (All Configurations)

5.1. C\C++ - General - Debug Information Format = Program Database (/Zi)
5.2. C\C++ - Preprocessor - Preprocessor Definitions = _X86_ [comment: add also DBG for Debug config]
5.3. C\C++ - Code Generation - Enable C++ Exceptions = No
5.4. C\C++ - Code Generation - Basic Runtime Checks = Default
5.5. C\C++ - Code Generation - Buffer Security Check = No (/GS-)
5.6. C\C++ - Advanced - Calling Convention = __stdcall (/Gz)
5.7. C\C++ - Advanced - Compile As = Compile as C Code (/TC) [comment: of course if you are going to use plain C]

5.8. Linker - General - Output File = $(OutDir)\$(ProjectName).sys
5.9. Linker - General - Enable Incremental Linking = Default
5.10. Linker - Input - Additional Dependencies = ntoskrnl.lib hal.lib $(NOINHERIT) [comment: you should add

needed libs here e.g. ntoskrnl.lib hal.lib]
5.11. Linker - Input - Ignore All Default Libraries = Yes (/NODEFAULTLIB)
5.12. Linker - Manifest File - Generate Manifest = No
5.13. Linker - System - SubSystem = Native (/SUBSYSTEM:NATIVE)
5.14. Linker - System - Driver = Driver (/DRIVER)
5.15. Linker - Advanced - Entry Point = DriverEntry
5.16. Linker - Advanced - Base Address = 0x10000

6. OK. Have done. Now you can test it with simple code, e.g.:

#include "ntddk.h"

NTSTATUS
DriverEntry(
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath
)
{
return STATUS_UNSUCCESSFUL;
}


If you have founded some mistakes or misundestoods please let me know.

Good Luck guys.