Низкоуровневое приложение C ++ падает в Windows Vista / 7, если не запущено в режиме совместимости с XP - PullRequest
3 голосов
/ 30 января 2010

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

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

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

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

EDIT:

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

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

IOCTL, которые я вызываю, включают IOCTL_DISK_GET_PARTITION_INFO_EX, IOCTL_STORAGE_GET_DEVICE_NUMBER, IOCTL_DISK_GET_LENGTH_INFO и IOCTL_DISK_GET_DRIVE_LAYOUT_.

Ответы [ 2 ]

1 голос
/ 23 февраля 2010

Это очень странно, но я вызывал 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'); и только на некоторых машинах это приведет к повреждению памяти.

Независимо от размера перераспределения (даже при попытке выделения дополнительных 256 символов!) Это может привести к повреждению кучи даже при использовании vector<unsigned char> в качестве буфера FILE_FS_VOLUME_INFORMATION.

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

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

0 голосов
/ 30 января 2010

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

...