где cmd.exe хранит историю команд ?

Тема в разделе "WASM.WIN32", создана пользователем necrostaz, 11 дек 2008.

  1. necrostaz

    necrostaz New Member

    Публикаций:
    0
    Регистрация:
    19 апр 2008
    Сообщения:
    17
    Никак не могу найти где cmd.exe хранит или инициализирует историю команд. Есть подозрение что история хранится в crss, но все равно где-то должен быть код инициализации, но, блин, никаких вызовов апи и lpc по теме в cmd не нашел. Глухо совсем, запарился уже (( Может кто, сильный в дизасме, поможет а ?
     
  2. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    necrostaz
    "История команд" - это когда стрелкой вверх предыдущая команда?
    Afaik такая "история" живет в рамках конкретного экземпляра cmd-процесса.
    Причем тут crss и lpc?
     
  3. necrostaz

    necrostaz New Member

    Публикаций:
    0
    Регистрация:
    19 апр 2008
    Сообщения:
    17
    ага
    А вот не совсем. Обьясняю ситуацию. Запускаю cmd, создаю на ней RemoteThread в котором отключаю процесс cmd.exe от консоли (вызываю FreeConsole), затем опять создаю удаленный поток в котором обратно подключаю cmd к консоли (AttachConsole), при этом история команд теряется. Теперь интересный момент. Если в этом процессе cmd запустить новый cmd, то история команд таинственным образом восстанавливается. От старого, а ведб процесс то новый, это наводит на мысль что буфер хранится не в контексте процесса cmd, но инициализируется оттуда.

    Дело в том, консоль в винде, как я понял, штука серверная. И управляется она crss. Консольный процесс подключается к консоли, и посредством апи шлет lpc сообщения crss. Все консольные апи, так или иначе, вызывают CrsClientCallServer. Проблема в том что я не могу найти место в cmd,где вызывается что либо похожее на инициализацию истории ((
     
  4. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    necrostaz
    Ты прав, история хранится в сервере консольной подсистемы(csrss процесс). Ни какие события, ни какие сервисы не вызываются, всё происходит в csrss при перелистывании истори, выделении мышью и тп.(ну разуметсо win32k память меняетсо при любом изменении окна).
     
  5. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    necrostaz
    Соглашусь, что история принадлежит "консоли", а не процессу в ней запущеному.
    Написал тестик
    Код (Text):
    1. #define STRICT
    2. #define WIN32_LEAN_AND_MEAN
    3. #include <windows.h>
    4.  
    5. #pragma comment(linker, "/subsystem:console /entry:start")
    6. #pragma comment(lib, "kernel32.lib")
    7. #pragma comment(lib, "user32.lib")
    8.  
    9. #define DIMOFARRAY(x) (sizeof(x)/sizeof(x[0]))
    10.  
    11. static int dbgA(char *format, ...)
    12. {
    13.   char buffer [1024];
    14.   wvsprintfA(buffer, format, format + sizeof(format));
    15.   OutputDebugStringA(buffer);
    16.   return 1;
    17. }
    18.  
    19. static int getsA(char *buffer, unsigned int size)
    20. {
    21.  
    22.   const DWORD mode = ENABLE_LINE_INPUT |
    23.                      ENABLE_ECHO_INPUT |
    24.                      ENABLE_PROCESSED_INPUT;
    25.   DWORD read = 0;
    26.  
    27.   HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
    28.   if (INVALID_HANDLE_VALUE == h)
    29.   {
    30.     dbgA("getsA: GetStdHandle(STD_INPUT_HANDLE) failed %08X", GetLastError());
    31.     return 0;
    32.   }
    33.  
    34.   if (0 == SetConsoleMode(h, mode))
    35.   {
    36.     dbgA(TEXT("getsA: SetConsoleMode failed %08X"), GetLastError());
    37.     return 0;
    38.   }
    39.  
    40.   if (0 == ReadFile(h, buffer, size-1, &read, NULL))
    41.   {
    42.     dbgA("getsA: ReadFile failed %08X", GetLastError());
    43.     return 0;
    44.   }
    45.  
    46.   if (0 == read)
    47.   {
    48.     dbgA("getsA: EOF reached");
    49.     return -1;
    50.   }
    51.  
    52.   buffer[ read ] = '\0';
    53.  
    54.   return read;
    55. }
    56.  
    57.  
    58. void start(void)
    59. {
    60.   TCHAR buffer [1024];
    61.  
    62.   while (getsA(buffer, DIMOFARRAY(buffer)) > 0) ;
    63.  
    64.   if (0 == FreeConsole())
    65.     dbgA("start: FreeConsole failed %08X", GetLastError());
    66.   else
    67.   {
    68.     dbgA("start: FreeConsole ok");
    69.     Sleep(1000);
    70.     if (0 == AllocConsole())
    71.       dbgA("start: AllocConsole failed %08X", GetLastError());
    72.     else
    73.     {
    74.       dbgA("start: AllocConsole ok");
    75.       while (getsA(buffer, DIMOFARRAY(buffer)) > 0) ;
    76.     }
    77.   }
    78.  
    79.   return;
    80. }
    можно собрать, запустить, ввести несколько строк и клавишами стрелок вверх/вниз посмотреть на историю. Нажать F6<enter>, сгенерировав EOF. Консоль будет освобождена, пауза, консоль будет создана. Предыдущей истории в ней уже нет, новую можно набрать.

    Вопрос: поясни, к какой консоли ты прицеплялся, когда "подключаю cmd к консоли (AttachConsole) ... Если в этом процессе cmd запустить новый cmd, то история команд таинственным образом восстанавливается."?
     
  6. necrostaz

    necrostaz New Member

    Публикаций:
    0
    Регистрация:
    19 апр 2008
    Сообщения:
    17
    Это потому что ты создаешь новую консоль, а старую убиваешь. У меня ситуация иная. Поясню, у меня два процесса на самом деле. Cmd и мой процесс, мой запускается из cmd, затем подключается к ее консоли (AttachConsole), потом замораживает cmd и отключает ее от консоли удаленным потоком, консоль при этом не убивается, т.к. мой процесс остается к ней поключенным, потом в конце работы моего процесса я поключаю cmd обратно к этой же консоли и размораживаю ее процесс. При этом грохается история, причем новая тоже не набирается. А если потом, уже после завершения моего процесса, в этой же консоли запустить новый cmd, то старая история восстанавливается. Я тут топик создавал по-этому поводу
    http://www.wasm.ru/forum/viewtopic.php?id=29815. Просто моему гуевому приложению понадобился консольный вывод, отсюда и все эти извраты. А теперь вот историю понадобилось восстановить.

    По сабжу: Я, очевидно, затупил - cmd не инициализирует историю, ее инициализирует crss, а при вызове FreeConsole видимо ее отключает, но почему тогда при запуске нового cmd восстанавливается старая ? Сrss буферы чтоли очистить забывает?
     
  7. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    necrostaz
    > Я тут топик создавал по-этому поводу
    Видел и не понял: "при аттаче к родительской консоли ... ввод от cmd также направляется в консоль, т.е. если юзер вздумает например нажать Enter то вывод превратится в кашу".

    > но почему тогда при запуске нового cmd восстанавливается старая
    Попробуй так. Запусти cmd, набери историю команд, очередной командой запусти cmd, она не видит историю предыдущей/родителя. Создай историю в ней. Выполни exit, окажешься в первой cmd'е она помнит только свою историю. Опять запусти cmd. Чудеса - она знает историю не родителя, а своей сестренки.

    Может быть, стОит пересмотреть идеологию программы, вместо борьбы с ядром?
     
  8. necrostaz

    necrostaz New Member

    Публикаций:
    0
    Регистрация:
    19 апр 2008
    Сообщения:
    17
    Да все просто, консоль - сервер, к ней подключены 2 процесса - cmd и мой, у каждого есть свой вывод и ввод с эхом, и все это вместе идет на эту консоль. Ситуация такая - мой процесс что то там выводит, но при этом юзер может что-то вводить и исполнять команды в cmd.

    Ага. Очень интересно. Наверняка какие-нить связанные списки....только все равно это гадание на кофейной гуще ))

    Да уже как бы пересмотрел ))... Просто интересно эту задачку все таки решить