Archive

Posts Tagged ‘Программирование’

Битва титанов: Visual Studio 2010 против Sophos Antivirus.

May 4th, 2012 37 comments

По рассылке пришло описание бага ну просто феерической кавайности: http://connect.microsoft.com/VisualStudio/feedback/details/649139/vs2010-does-complete-rebuild-based-on-completely-unrelated-file. Если вкраце, то присутсвие Sophos Antivirus на машине, заставляет Visual Studio делать полный билд вместо инкрементального. Почему? Потому что MSBuild полагает, что файл “%ProgramData%\Sophos\Sophos Anti-Virus\config\Config.bops” (который, понятно, ни к MSBuild, ни к собираемому проекту никак не относится) является вводом каждого target’а в проекте. По какой-то причине, этот файл обновляется очень часто, что и вызывает полную пересборку всего проекта. WTF?

WTF?

Read more…

Уведомления о смене состояния.

February 21st, 2012 Comments off

А давайте разберем антипаттерн – реализацию механизма уведомления о смене состояния чего-либо с помощью очереди сообщений. Для примера возьмем Session Change Notifications в Windows. Пример, как очевидно, совершенно произвольный и не имеющий никакого отношения к тому, что я их сегодня полдня ковырял. :-)

По идее, все просто. Хотим отслеживать состояние сессий – регистрируем окошко или обработчик, куда будут посылаться уведомления о смене состояния сессий и все дела. Если присмотреться, то все не так просто. Как, к примеру, синхронизировать получение начального состояния всех сессий и установку обработчика? Оба действия не атомарны и, следовательно, можно либо пропустить некоторые уведомления, либо получить уведомления, уже учтенные начальным состоянием сессий. Или другая проблема: состояние сессии, вычисленное по полученным уведомлениям может не соответствовать актуальному состоянию сессии. Т.е. получаем WTS_SESSION_LOGON, а сессия уже давно завершилась и даже соответствующее уведомление было послано, просто сообщение все еще сидит в очереди оконных сообщений необработанное. Именно с сессиями, такое вряд ли конечно может случиться на практике. Слишком они тяжеловесны. Но теоретически такое возможно. Хотя стресс тесты и не такое, бывает, находят.

Возникает вопрос, а что же делать? Одно из возможных решений – разделить доставку уведомления о смене состояния и получение текущего состояния. Получение уведомления будет означать, что состояние, возможно, поменялось. Обработчик уведомления должен будет опросить текущее состояние и сравнить его с сохраненной копией. Опять же, в моем случае, все что мне нужно было отследить – это номер сессии, присоединенной в физической консоли. Для этого есть отдельная, и очень эффективная функция – WTSGetActiveConsoleSessionId(). Вот её полный листинг:

0:000> uf kernel32!WTSGetActiveConsoleSessionId
kernel32!WTSGetActiveConsoleSessionId:
75133f49 a1d802fe7f      mov     eax,dword ptr [SharedUserData+0x2d8 (7ffe02d8)]
75133f4e c3              ret

:-)

При таком подходе представления обработчика о текущем состоянии гораздо ближе к реальности, однако некоторые переходы между состояниями могут быть пропущены. В прочем, для асинхронных уведомлений это возможно в любом случае.

Можно ли использовать функцию RtlCaptureContext() из x86 кода?

July 24th, 2011 2 comments

Вопрос из почты:

The question is really simple: could we use RtlCaptureContext on X86? The MSDN (http://msdn.microsoft.com/en-us/library/ms680659(v=VS.85).aspx) says it’s only for 64 but the bug is for X86 and I see some kernel code are using it on x86.

Вопрос на самом деле очень прост: можем ли мы использовать функцию RtlCaptureContext на x86? MSDN говорит, что эта функция только для 64-х бит но баг-репорт (имеется ввиду баг-репорт, ранее упомянутый в письме) воспроизводится для x86 и я вижу, что код в ядре использует эту функцию на x86.

Ответ: можно. Действительно, упомянутая страница MSDN утверждает, что:

The following functions are used only on 64-bit Windows.

Следующие функции используются только в 64-х разрядных версиях Windows.

Однако, страница, описывающая саму функцию RtlCaptureContext() указывает Windows XP и Windows Server 2003 в качестве минимальных версий клиента и сервера. Сравните с функцией RtlAddFunctionTable(), действительно не реализованной на x86. Минимальные версии клиента и сервера для неё – Windows XP Professional x64 Edition и 64-bit editions of Windows Server 2003 соответственно.

Другой способ удостовериться в этом – проверить таблицу экспорта NTDLL. Хотя такой способ, конечно, не дает никакой информации о том, документирована функция (иными словами – поддерживается ли обратная совместимость для неё) или нет.

C:\>link /dump /exports c:\Windows\SysWOW64\ntdll.dll | findstr RtlCaptureContext
        667  28D 00046B2B RtlCaptureContext

C:\>link /dump /exports c:\Windows\SysWOW64\ntdll.dll | findstr RtlAddFunctionTable

C:\>

Функция DeviceIoControlEx.

June 14th, 2011 2 comments

Win32 API предоставляет «Ex» варианты функций ReadFile и WriteFile, в то время как «Ex» варианта функции DeviceIoControl не предлагается. Исправить этот недостаток очень просто, так как соответствующая функция Native API документирована в MSDN: NtDeviceIoControlFile (хотя и помечена как «Deprecated»). Прототип новой функции будет выглядеть вот так:

Read more…

Неогороженное минное поле – это еще не повод по нему ходить.

June 8th, 2011 9 comments

Пришло письмо с вопросом:

Обнаружилась следующая проблема:

Наша программа сохраняет и считывает последнюю открытую ею директорию в разделе реестра, где сохраняют последние посещенные ими директории и другие программы, а именно в ветке «HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRU». Это в 32-х разрядной версии. Но оказывается, что в 64-х разрядной версии данной ветки реестра в узле HKCU не существует, а она находится в «HKEY_USERS\<некий идентификатор пользователя>\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRU».

Так вот вопрос: как мне программно доступиться к этой ветке, если идентификатор пользователя неизвестен? Или, может, есть способ узнать этот идентификатор каким-то образом? А может где-то есть в реестре зеркало этой ветки, к которой можно получить доступ более простым способом?

Read more…

Список состояний конечного автомата.

May 15th, 2011 8 comments

Подсмотрел у коллеги простой и довольно удобный способ держать список состояний/событий конечного автомата в одном месте. А то обычно они норовят расползтись по разным углам: enum, объявляющий соответствующие константы, массив имен состояний для отладки, большой switch, выбирающий что делать, в зависимости от состояния…

Read more…

РИТ++, секция «RootConf».

April 2nd, 2011 4 comments

Меня пригласили выступить на конференции РИТ++ 2011, которая пройдет в Москве в конце апреля. Предварительная тема доклада: «Сетевая подсистема Windows глазами разработчика. Краткий, неполный и, в основном, неверный обзор. :-) » Я собираюсь рассказать о том, как работает ядерная часть сетевой подсистемы, как данные попадают в user mode и что с ними происходит по пути. Заходите на огонёк.