Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Pascal > Резидент


Автор: Krishkinn 23.12.03, 15:08
Кто знает как написать резидента, который мог бы что-нибудь печатать в других прогах. Вообщем 'имитировал' нажатие клавиш. Все это естественно под MS-DOS huh.gif

Автор: Some1 23.12.03, 16:14
Давай напишем. Только что должно печататься? Какой, и когда это должно активироваться ?

Автор: Krishkinn 23.12.03, 18:17
Это прога для экзаменов. Запускаешь её, указываешь номер билета, а она берет уже готовый исходник. Далее заходишь в Pascal нажимаешь на любые клавиши, а резидент пишит не то что нажато а готовый исходник.

!!!Мне только надо узнать, как имитировать нажатие клавиш(отсылать в KEY-буфер нужную клавишу).

Автор: Some1 24.12.03, 04:00
Вот, но правда тут всё молодо, зелено %)) Нужно ещё дорабатывать. Лучше закоментируй пока строку keep, и поставь перед ней writeln (для тестирования).
Я туда ещё много чего прифинтычу. Например буффер для текстовых данных. Ты скажи мне, какого максимум размера у тебя в билетах ответ ? Сколько мне памяти под прогу отводить ? или лучше читать из файла ? Тогда придётся самому писать чтение из файла. На асме (паскалевое не подойдёт). Хотя.. ммм.. хотя придумаем... главное время. А его у меня маловато свободного.

Программа подменяет нажатия основных (не управляющих)клавиш на строку s2. Когда строка кончается Имитирует ENTER (#13). Поэтому тестировать лучше всего readln'ом
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    Program Resident;
    {Говорим компилятору, что все юниты имеют общий сегмент данных}
    {$G+}
    {Не будем использовать кучу}
    {$M 4072,0,0}
    uses dos;
    const
      Stacksize = 2*512; {512 - Количество слов в стеке}
      s2:string='Привет всем кто меня знает !!!'+#13;
      p:word=1;
    var
      oldint09:pointer;
      temp:word;
     
    {$F+}
    {Процедура обработки прерывания}
    procedure MyInt; Interrupt;
    begin
      asm
        jmp @skip
        db 14,'Мой резидент 2'
        @skip:
      end;
      temp:=memw[$0040:$001c];
      asm
        db $9c
        call oldint09
      end;
      if temp<>memw[$0040:$001c] then
      if((mem[$0040:memw[$0040:$001A]]<>0)and
         (mem[$0040:memw[$0040:$001A]]<>224))
     
         or(memw[$0040:memw[$0040:$001A]]=224) then
      begin
        mem[$0040:memw[$0040:$001A]]:=byte(s2[p]);
        if s2[p]='р' then mem[$0040:memw[$0040:$001A]+1]:=0;
        if p<length(s2) then inc(p);
      end;
    end;
    {$F-}
     
    var
      ptr1:pchar; {Указатель на предпологаемый резидент}
      s:string[14]; {Проверочная строка}
    begin
      getintvec($09,pointer(ptr1)); {Узнаем адрес вектора}
      {Скопируем из содержимого предпологаемого резидента проверочную строку}
      {Смещение - 18 это смещение проверочной строки от начала резидента}
      move(ptr1[18],s,15); {15 - количество букв + 1 байт на размер строки}
      if s='Мой резидент 2' then
      begin
        writeln('Программа уже запущена.');
        exit;
      end;
      GetIntVec($09,OldInt09);
      SetIntVec($09,Addr(MyInt));
      Keep(0);
    end.

Автор: Krishkinn 24.12.03, 10:19
Я тут чуть изменил Ваш исходник. Теперь прога берет все из файла и печатает это. Также она включается/выключается при нажатии на '~'

Program Resident;
{Говорим компилятору, что все юниты имеют общий сегмент данных}
{$G+}
{Не будем использовать кучу}
{$M 4072,0,0}
uses dos;
const
  Stacksize = 2*512; {512 - Количество слов в стеке}
  name='txt.txt';
  quit='~';
var
  oldint09:pointer;
  temp:word;
  i,kolvo:longint;
  power:boolean;
  ch:char;
{$F+}
{Процедура обработки прерывания}
procedure MyInt; Interrupt;
begin
  asm
    jmp @skip
    db 14,'Мой резидент 2'
    @skip:
  end;
  temp:=memw[$0040:$001c];
  asm
    db $9c
    call oldint09
  end;
  if mem[$0040:memw[$0040:$001A]]=ord('~') then power:=not power;

  if power then
    if temp<>memw[$0040:$001c] then
      if((mem[$0040:memw[$0040:$001A]]<>0)) then
      begin
        inc(kolvo);
        reset(input);
        i:=0;
        while (ch<>#26)and(i<kolvo) do
        begin
          read(ch);
          inc(i);
        end;
        close(input);
        if ch=#26 then
        begin
          power:=false;
        end else mem[$0040:memw[$0040:$001A]]:=ord(ch);
      end;

end;
{$F-}

var
  ptr1:pchar; {Указатель на предпологаемый резидент}
  s:string[14]; {Проверочная строка}
begin
  assign(input,name);
  kolvo:=0;
  power:=false;
  getintvec($09,pointer(ptr1)); {Узнаем адрес вектора}
  {Скопируем из содержимого предпологаемого резидента проверочную строку}
  {Смещение - 18 это смещение проверочной строки от начала резидента}
  move(ptr1[18],s,15); {15 - количество букв + 1 байт на размер строки}
  if s='Мой резидент 2' then
  begin
    writeln('Программа уже запущена.');
    exit;
  end;
  GetIntVec($09,OldInt09);
  SetIntVec($09,Addr(MyInt));
  Keep(0);
end.

Автор: Some1 24.12.03, 10:55
Нашёл два (как минимум) глюка:
Во первых если в тексте программы, которую печатаем будет "~", то всё обрубится.
Во вторых я убрал, а ты добавил глюк с русской буквой "р". Она не печатается. Для того, чтобы правильно её положить в буффер обмена, нужно в соседнюю ячейку буффера положить вместе с ней ноль (как было у меня): "if s2[p]='р' then mem[$0040:memw[$0040:$001A]+1]:=0;".

И ты решил, что при нажатии любой клавиши (даже управляющей типа стрелок курсора) будет выводиться текст из файла. Чтож, это твоё решение %) Может так даже лучше. Я просто старался сделать так, чтобы текст выводился только при нажати на буквы, цифры, всякие знаки, но на стрелки и F клавиши не выводился бы %)

Автор: Krishkinn 24.12.03, 13:08
Насчет первого глюка. Символ ~ никогда не встречается в исходниках Pascal.
Насчет второго глюка. Эта ошибка возникает только с символом "р" или есть еще какие-нибудь символы?

Заранее спасибо.

Автор: Some1 24.12.03, 13:37
1. Не правда. Я вот проверял резидент на её собственном тексте. И там встретил такой символ %))))))))))
2. известный глюк. Только с этим символом. Его номер совпадает с кодом управляющих символов. И поэтому нужно проверять, и если сканкод (следующий байт в буффере клавиатуры) равен 0, а сама клавиша - "р" (кажется 229) то это буква "р". Иначе это управляющая клавиша. И, соответственно, если ты подменяешь клавиши, то для всех обычных букв тебе достаточно поменять один байт. А чтобы поместить в буффер букву "р" тебе нужно ещё сбросить в ноль следующий байт (как у меня в проге).

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)