Никак не могу найти где cmd.exe хранит или инициализирует историю команд. Есть подозрение что история хранится в crss, но все равно где-то должен быть код инициализации, но, блин, никаких вызовов апи и lpc по теме в cmd не нашел. Глухо совсем, запарился уже (( Может кто, сильный в дизасме, поможет а ?
necrostaz "История команд" - это когда стрелкой вверх предыдущая команда? Afaik такая "история" живет в рамках конкретного экземпляра cmd-процесса. Причем тут crss и lpc?
ага А вот не совсем. Обьясняю ситуацию. Запускаю cmd, создаю на ней RemoteThread в котором отключаю процесс cmd.exe от консоли (вызываю FreeConsole), затем опять создаю удаленный поток в котором обратно подключаю cmd к консоли (AttachConsole), при этом история команд теряется. Теперь интересный момент. Если в этом процессе cmd запустить новый cmd, то история команд таинственным образом восстанавливается. От старого, а ведб процесс то новый, это наводит на мысль что буфер хранится не в контексте процесса cmd, но инициализируется оттуда. Дело в том, консоль в винде, как я понял, штука серверная. И управляется она crss. Консольный процесс подключается к консоли, и посредством апи шлет lpc сообщения crss. Все консольные апи, так или иначе, вызывают CrsClientCallServer. Проблема в том что я не могу найти место в cmd,где вызывается что либо похожее на инициализацию истории ((
necrostaz Ты прав, история хранится в сервере консольной подсистемы(csrss процесс). Ни какие события, ни какие сервисы не вызываются, всё происходит в csrss при перелистывании истори, выделении мышью и тп.(ну разуметсо win32k память меняетсо при любом изменении окна).
necrostaz Соглашусь, что история принадлежит "консоли", а не процессу в ней запущеному. Написал тестик Код (Text): #define STRICT #define WIN32_LEAN_AND_MEAN #include <windows.h> #pragma comment(linker, "/subsystem:console /entry:start") #pragma comment(lib, "kernel32.lib") #pragma comment(lib, "user32.lib") #define DIMOFARRAY(x) (sizeof(x)/sizeof(x[0])) static int dbgA(char *format, ...) { char buffer [1024]; wvsprintfA(buffer, format, format + sizeof(format)); OutputDebugStringA(buffer); return 1; } static int getsA(char *buffer, unsigned int size) { const DWORD mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT; DWORD read = 0; HANDLE h = GetStdHandle(STD_INPUT_HANDLE); if (INVALID_HANDLE_VALUE == h) { dbgA("getsA: GetStdHandle(STD_INPUT_HANDLE) failed %08X", GetLastError()); return 0; } if (0 == SetConsoleMode(h, mode)) { dbgA(TEXT("getsA: SetConsoleMode failed %08X"), GetLastError()); return 0; } if (0 == ReadFile(h, buffer, size-1, &read, NULL)) { dbgA("getsA: ReadFile failed %08X", GetLastError()); return 0; } if (0 == read) { dbgA("getsA: EOF reached"); return -1; } buffer[ read ] = '\0'; return read; } void start(void) { TCHAR buffer [1024]; while (getsA(buffer, DIMOFARRAY(buffer)) > 0) ; if (0 == FreeConsole()) dbgA("start: FreeConsole failed %08X", GetLastError()); else { dbgA("start: FreeConsole ok"); Sleep(1000); if (0 == AllocConsole()) dbgA("start: AllocConsole failed %08X", GetLastError()); else { dbgA("start: AllocConsole ok"); while (getsA(buffer, DIMOFARRAY(buffer)) > 0) ; } } return; } можно собрать, запустить, ввести несколько строк и клавишами стрелок вверх/вниз посмотреть на историю. Нажать F6<enter>, сгенерировав EOF. Консоль будет освобождена, пауза, консоль будет создана. Предыдущей истории в ней уже нет, новую можно набрать. Вопрос: поясни, к какой консоли ты прицеплялся, когда "подключаю cmd к консоли (AttachConsole) ... Если в этом процессе cmd запустить новый cmd, то история команд таинственным образом восстанавливается."?
Это потому что ты создаешь новую консоль, а старую убиваешь. У меня ситуация иная. Поясню, у меня два процесса на самом деле. Cmd и мой процесс, мой запускается из cmd, затем подключается к ее консоли (AttachConsole), потом замораживает cmd и отключает ее от консоли удаленным потоком, консоль при этом не убивается, т.к. мой процесс остается к ней поключенным, потом в конце работы моего процесса я поключаю cmd обратно к этой же консоли и размораживаю ее процесс. При этом грохается история, причем новая тоже не набирается. А если потом, уже после завершения моего процесса, в этой же консоли запустить новый cmd, то старая история восстанавливается. Я тут топик создавал по-этому поводу http://www.wasm.ru/forum/viewtopic.php?id=29815. Просто моему гуевому приложению понадобился консольный вывод, отсюда и все эти извраты. А теперь вот историю понадобилось восстановить. По сабжу: Я, очевидно, затупил - cmd не инициализирует историю, ее инициализирует crss, а при вызове FreeConsole видимо ее отключает, но почему тогда при запуске нового cmd восстанавливается старая ? Сrss буферы чтоли очистить забывает?
necrostaz > Я тут топик создавал по-этому поводу Видел и не понял: "при аттаче к родительской консоли ... ввод от cmd также направляется в консоль, т.е. если юзер вздумает например нажать Enter то вывод превратится в кашу". > но почему тогда при запуске нового cmd восстанавливается старая Попробуй так. Запусти cmd, набери историю команд, очередной командой запусти cmd, она не видит историю предыдущей/родителя. Создай историю в ней. Выполни exit, окажешься в первой cmd'е она помнит только свою историю. Опять запусти cmd. Чудеса - она знает историю не родителя, а своей сестренки. Может быть, стОит пересмотреть идеологию программы, вместо борьбы с ядром?
Да все просто, консоль - сервер, к ней подключены 2 процесса - cmd и мой, у каждого есть свой вывод и ввод с эхом, и все это вместе идет на эту консоль. Ситуация такая - мой процесс что то там выводит, но при этом юзер может что-то вводить и исполнять команды в cmd. Ага. Очень интересно. Наверняка какие-нить связанные списки....только все равно это гадание на кофейной гуще )) Да уже как бы пересмотрел ))... Просто интересно эту задачку все таки решить