2010-01-30 6 views
3

У меня низкий уровень (например, действительно низкоуровневый, это в основном все вызовы IOCTL и несколько вызовов API перечисления), который периодически падает на Windows Vista/7 на компьютерах клиентов. К сожалению, я не смог получить какие-либо аварийные дампы, но один полезный пользователь упомянул, что запуск программы в режиме совместимости с XP решил проблему.Сбой при работе на низком уровне C++ в Windows Vista/7 Если не работает в режиме совместимости с XP

Приложение всегда запускается с полными правами администратора (он запускается из другой программы, требующей авторизации администратора), поэтому это не проблема UAC. Я не использую устаревшие API, и я не полагаюсь на какие-либо хаки реестра и т. Д. Я просто выдаю вызовы для перечисления дисков, а затем с помощью команд IOCTL, чтобы получить более низкоуровневую информацию обо всех подключенных устройствах.

Что происходит в режиме совместимости XP? Что Windows вводит в мое приложение или иным образом изолирует его, что предотвращает его сбой в Vista/7? Я изначально подозревал, что куча повреждена (хотя я вытащил свои волосы, пытаясь воспроизвести или отследить проблему), прежде чем сказать, что он отлично работает в режиме совместимости с XP.

Может ли кто-нибудь предложить любые возможные проблемы, которых можно было бы избежать в режиме совместимости XP, на которые я должен попытаться решить эту проблему? Благодаря!

EDIT:

Еще одна вещь, которая, вероятно, очень важно отметить: я звоню функцию DDK/ядро ​​из пользовательского пространства для того, чтобы получить в определенных функциях, не подвергающихся через API WIN32.

Я использую ZwReadFile, ZwCreateFile, ZwWriteFile, RtlInitUnicodeString, ZwQueryVolumeInformationFile, ZwDeviceIoControlFile, ZwSetInformationFile, ZwClose.

В IOCTLs я звоню включают IOCTL_DISK_GET_PARTITION_INFO_EX, IOCTL_STORAGE_GET_DEVICE_NUMBER, IOCTL_DISK_GET_LENGTH_INFO и IOCTL_DISK_GET_DRIVE_LAYOUT_EX.

+0

Можете ли вы предоставить образец кода для этого? Какие конкретные вызовы IOCTL вы используете? Это больше похоже на проблему с драйвером ... – t0mm13b

+0

Я обновил сообщение. Я полностью забыл упомянуть о самой важной вещи, и это то, что я вызываю функции kernel/ddk из пользовательского пространства! Я также перечислил IOCTL, которые я использую. –

+0

Возможно, что IOCTL были изменены для Windows 7, когда вы считаете, что их загрузочный код отличается и поддержка Bitlocker (я мог бы быть в моей голове на этом) ... также, драйверы изменились для Win 7, который мог бы объяснить, что функции DDK не работают на 100% под Win 7 ... – t0mm13b

ответ

1

Это очень странно, но я вызывал ZwQueryVolumeInformationFile с FsInformationClass, установленным в FileFsVolumeInformation.

Я прошел в буфере FILE_FS_VOLUME_INFORMATION, который сначала нормально распределен, а затем помещается в (sizeof(FILE_FS_VOLUME_INFORMATION) + sizeof(TCHAR)*FILE_FS_VOLUME_INFORMATION->VolumeLabelLength).

Тогда я назвал FILE_FS_VOLUME_INFORMATION->VolumeLabel[FILE_FS_VOLUME_INFORMATION->VolumeLabelLength/2] = _T('\0'); и только на некоторых машинах это приведет к повреждению памяти.

Независимо от размера overallocation (даже пытались выделить целых 256 символов дополнительный!), То это будет надежно привести к куче коррупции даже при использовании vector<unsigned char> в качестве буфера FILE_FS_VOLUME_INFORMATION.

Кажется, что ядро ​​накладывает на буфер какую-то защиту от записи, что приводит к повреждению независимо от размера. Копирование первых байтов VolumeLableLength во второй буфер, , затем после ожидания _T('\0') решил проблему.Не знаете, как/почему Windows, делал буфер, я выделенный и передается в качестве параметра только для чтения или если он хранил после в FILE_FS_VOLUME_INFORMATION-структуру (который должен закончить с массивом символов!), А просто не изменяя какие-либо данные в буфере, который я передал, сделал трюк .... который сумасшедший, потому что это происходит только (последовательно и 100% воспроизводимо) на определенных машинах.

В любом случае: проблема решена * phew *!

+0

выглядит как ошибка для меня: вы используете sizeof (TCHAR), но VolumeLabel - это WCHAR, нет версии ANSI. Затем ваше задание записывает конец массива. –

+0

Нет. Они оба являются широкими символами (определен UNICODE), а NULL * * помещается в нужное место (проверяется посредством журналов и дампов памяти). –

0

Было много изменений в драйверах низкого уровня с XP на Vista. Я подозреваю, что вы используете IOCTL, на который это влияет.

+0

Am, этот код работает над более чем десятком тестовых машин с различными перестановками Windows Vista/7 на широко распространенном оборудовании. Некоторые аппаратные/программные комбинации приводят к сбою. Все IOCTL, которые я использую, поддерживаются в Vista/7. –

+0

@Computer Guru: Какие определенные конфигурации жестких/программных продуктов отличаются от остальных, которые вызывают крах? – t0mm13b

+0

В первую очередь таблица разделов. Код Win32 по-прежнему имеет очень хорошую поддержку GUID-разделенных жестких дисков (OS X-style), и это одна из причин, по которым я вручную делаю что-то из DDK. –