четверг, 1 октября 2009 г.

Самый странный способ определить Windows NT

Это перевод The strangest way of detecting Windows NT. Автор: Реймонд Чен.

Один мой коллега номинировал этот код на звание Функции Года (да, это тот же человек, который первым сообщил, что бета Windows использует подозрительные URL). Я должен признать, что этот код довольно впечатляет. Вы должны согласиться, что использовать недокументированные детали реализации проецируемых в память файлов из всех способов проверить версию операционной системы - определённо является креативным!

// Внимание: ошибочный код!
function AreWeRunningOnWindowsNT: Boolean;
var
hFile, hFileMapping: THandle;
pbFile, pbFile2: PAnsiChar;
szFile: array[0..MAX_PATH - 1] of Char;
begin
GetSystemDirectory(szFile, MAX_PATH);
hFile := CreateFile(PChar(szFile + '\MAIN.CPL'), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nil);

hFileMapping := CreateFileMapping(hFile, nil, PAGE_READWRITE, 0, 0, nil);

pbFile := MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, 0);

pbFile2 := MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 65536, 0);

Result := ((pbFile + 65536) <> pbFile2);
end;

Даже не обращайте внимания, что функция оставляет файл заблокированным и теряет два дескриптора каждый раз, когда вы вызываете её!

Даже больше: функция может ошибочно возвращать False на машине с Windows NT, если, по удивительному совпадению, менеджер памяти пристыкует вторую проекцию файла к следующему же блоку в 64 Кб (это не запрещено, поскольку гранулярность адресного пространства равна 64 Кб).

Она также может ошибочно возвращать True на машинах с Windows 95, если файл MAIN.CPL будет меньше, чем 64 Кб, или у вас не будет прав на него (заметьте, что программа требует доступ на чтения-запись для файла MAIN.CPL).

Эта конкретная функция располагается в библиотеке, которая используется многими multimedia программами с Большим Именем.

Быстрейшим способом определить, запущены ли вы под системой типа Windows 95 или Windows NT - использовать надеюсь-очевидно-названную функцию GetVersion.

function AreWeRunningOnWindowsNT: Boolean;
begin
Result := (GetVersion and $80000000) = 0;
end;


Прим.пер.: на Delphi чаще всего это удобнее делать так:

function AreWeRunningOnWindowsNT: Boolean;
begin
Result := (Win32Platform = VER_PLATFORM_WIN32_NT);
end;


Win32Platform - это поле dwPlatformId, возвращаемое GetVersionEx. Кстати, в описании OSVERSIONINFOEX и OSVERSIONINFO есть таблички, показывающие как можно отличить одну версию Windows от другой (ну, исключая совсем древние системы).

Комментариев нет:

Отправить комментарий

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку.

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.

Примечание. Отправлять комментарии могут только участники этого блога.