Blog. Just Blog

Программное отключение и подключение монитора

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Программное отключение и подключение монитора
Программное отключение и подключение монитора

С программным выключением мониторов уже разобрались, сегодня разберем более жесткое действие - отключение. Принципиальную разницу между выключением и отключением, надеюсь, объяснять не надо. Конечно, программно выдернуть видеокабель из системника невозможно, но можно сделать так, чтобы система просто перестала воспринимать этот монитор.

Начинаем, как обычно, с описания структур и констант, которые понадобятся для работы. Что-то уже было, что-то добавилось новое. Главное, что FASM "из коробки" о них ничего не знает.
  1. struct  DISPLAY_DEVICE
  2.         cb           dd ?
  3.         DeviceName   rb 32
  4.         DeviceString rb 128
  5.         StateFlags   dd ?
  6.         DeviceID     rb 128
  7.         DeviceKey    rb 128
  8. ends
  9.  
  10. struct DEVMODE
  11.         dmDeviceName    rb 32
  12.         dmSpecVersion   dw ?
  13.         dmDriverVersion dw ?
  14.         dmSize          dw ?
  15.         dmDriverExtra   dw ?
  16.         dmFields        dd ?
  17.         dmPosition      POINT ?
  18.         dmDisplayOrientation dd ?
  19.         dmDisplayFixedOutput dd ?
  20.         dmColor         dw ?
  21.         dmDuplex        dw ?
  22.         dmYResolution   dw ?
  23.         dmTTOption      dw ?
  24.         dmCollate       dw ?
  25.         dmFormName      rb 32
  26.         dmLogPixels     dw ?
  27.         dmBitsPerPel    dd ?
  28.         dmPelsWidth     dd ?
  29.         dmPelsHeight    dd ?
  30.         dmDisplayFlags  dd ?
  31.         dmNup           dd ?
  32.         dmDisplayFrequency dd ?
  33.         dmICMMethod     dd ?
  34.         dmICMIntent     dd ?
  35.         dmMediaType     dd ?
  36.         dmDitherType    dd ?
  37.         dmReserved1     dd ?
  38.         dmReserved2     dd ?
  39.         dmPanningWidth  dd ?
  40.         dmPanningHeight dd ?
  41. ends
  42.  
  43. EDD_GET_DEVICE_INTERFACE_NAME = 1
  44. ENUM_REGISTRY_SETTINGS  = 0FFFFFFFEh
  45.  
  46. CDS_UPDATEREGISTRY      = 1
  47. CDS_NORESET             = 10000000h
  48.  
  49. DM_PELSWIDTH            = 00080000h
  50. DM_PELSHEIGHT           = 00100000h
  51. DM_POSITION             = 00000020h
Трюк с отключением монитора основан на применении к нему кривых настроек. В этом случае система справедливо полагает, что с монитором что-то не так и исключает его из обработки. Способ, конечно, варварский, но иначе никак. Код для отключения монитора будет таким:
  1.         ; Второй монитор
  2.         mov     [device],1
  3.  
  4.         ; Отключить монитор
  5.         mov     [dds.cb],sizeof.DISPLAY_DEVICE
  6.         invoke  EnumDisplayDevices,NULL,[device],dds,\
  7.                 EDD_GET_DEVICE_INTERFACE_NAME
  8.         invoke  RtlZeroMemory,dmode,sizeof.DEVMODE
  9.         mov     [dmode.dmSize],sizeof.DEVMODE
  10.         mov     [dmode.dmFields],DM_PELSHEIGHT+DM_PELSWIDTH+DM_POSITION
  11.         invoke  ChangeDisplaySettingsEx,dds.DeviceName,dmode,0,\
  12.                 CDS_UPDATEREGISTRY+CDS_NORESET,NULL
  13.         invoke  ChangeDisplaySettingsEx,NULL,NULL,0,0,NULL
Подготавливаем настройки устройства, заполняя структуру DEVMODE нулями. После этого применяем кривые настройки монитора при помощи функции ChangeDisplaySettingsEx. Как показывает практика, для отключения монитора достаточно обнулить значения ширины и высоты пиксела, о чем указывают комбинация флагов DM_PELSHEIGHT и DM_PELSWIDTH. При необходимости можно усилить ударную комбинацию флагами DM_DISPLAYFREQUENCY и DM_DISPLAYFLAGS. Использование флага CDS_NORESET сообщает системе, что новые настройки монитора надо применить, но сохранять насовсем их не надо. Повторное применение настроек с нулевыми параметрами динамически изменяет настройки на остальных мониторах. При выполнении кода указанный монитор отключается, но остальные мониторы тоже здорово колбасит, несколько секунд они моргают и перезагружаются, после чего изображение на них восстанавливается. В панели управления отключенный программно монитор выглядит примерно так:

Монитор №2 отключен
Монитор №2 отключен

Физически монитор присутствует, но никаких манипуляций с ним выполнить нельзя. На самом мониторе появляется надпись об отсутствии сигнала, после чего он переходит в режим ожидания.

Для подключения монитора достаточно просто вернуть обратно корректные настройки. При помощи функции EnumDisplaySettings загружаем корректные настройки монитора из реестра, после чего точно так же применяем их к нужному устройству. Какие параметры были изменены, такие и надо восстановить, указав соответствующую комбинацию флагов.
  1.         ; Второй монитор
  2.         mov     [device],1
  3.  
  4.         ; Подключить монитор
  5.         mov     [dds.cb],sizeof.DISPLAY_DEVICE
  6.         invoke  EnumDisplayDevices,NULL,[device],dds,\
  7.                 EDD_GET_DEVICE_INTERFACE_NAME
  8.         mov     [dmode.dmSize],sizeof.DEVMODE
  9.         invoke  EnumDisplaySettings,dds.DeviceName,\
  10.                 ENUM_REGISTRY_SETTINGS,dmode
  11.         mov     [dmode.dmFields],DM_PELSHEIGHT+DM_PELSWIDTH+DM_POSITION
  12.         invoke  ChangeDisplaySettingsEx,dds.DeviceName,dmode,0,\
  13.                 CDS_UPDATEREGISTRY+CDS_NORESET,NULL
  14.         invoke  ChangeDisplaySettingsEx,NULL,NULL,0,0,NULL
Монитор возвращается к работе, но все равно придется зайти в настройки Персонализации, восстановить обои. Также придется заглянуть и в настройки мониторов, исправить их раскладку и поведение рабочего стола. Не исключено, что слетит еще что-то. Во время экспериментов мне даже пришлось перезагружать компьютер, потому что в какой-то момент изображение на мониторе совсем пропало и не восстанавливалось. Короче, минусов у такого метода гораздо больше, чем плюсов, поэтому использовать его на практике очень не рекомендую. Ну разве что для какого-нибудь вредительства, но это уже остается на вашей совести.

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

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Monitor.Add.Remove.zip (1,896 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 1629 | Комментариев: 3

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
ManHunter (01.12.2020 в 12:30):
На самом деле подобный код действительно является если не вредоносным, то уж точно крайне нежелательным к использованию, о чем я сам предупреждаю в статье.
NeshAliNehrin (01.12.2020 в 12:03):
Спасибо за возможность расширить кругозор.
Антивирус Касперского отправил архив в топку и попытался назвать сайт неблагонадёжным, что удручает.
Однако ситуация, когда пользователей интернета держат за подростков, клеящих жвачку на поручни, довольно неприятная.
Сохраняю доверие как к автору статей, так и к контенту сайта. Мой комментарий - просто факт возмущения тем, что хороший досуг портят необъективные, совершено посторонние люди.
Aleksandr (10.11.2020 в 21:14):
Благодарю за столь познавательную статью ув. ManHunter

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.09 сек. / MySQL: 2 (0.0063 сек.) / Память: 4.5 Mb
Наверх