MVV

|
Posted: Mon Apr 19, 2010 18:04 Post subject: |
|
|
HankHank wrote: | Попробовал приладить код с вызовом фонового процесса, получилось так:
Компиллятор не взбрыкнул. Нужный процесс рождается. Код возврата thread ненулевой. Но эффекта - нет. Так и стоим на месте - на [..]. Подробнее пока не глядел.
Может, свежим взглядом косяк виден сразу ? |
Ну молодец! Так и до вылета ТК в трубу недалеко.
А теперь поясняю, что у тебя происходит. Ты выделил в стеке место для буфера и вписал в него путь. Далее, ты вызываешь фоновую функцию и передаешь ей адрес этого буфера, и не дожидаясь ее завершения выходишь из функции, в которой буфер был выделен, то есть, уничтожаешь его! Что будет? Система при отправке сообщения WM_COPYDATA скопирует указанное число байт по указанному адресу в свой буфер (заметь, там уже может быть что угодно, так как основной поток продолжает работать и использовать стек по своему усмотрению) и отправит сообщение ТК, указав новый адрес буфера (функция позволяет передавать буфера между процессами, поэтому она переписывает данные в буфер в адресном пространстве процесса-получателя). Итак, ТК просто получит мусор. Но хрен его знает, насколько правильно он этот мусор интерпретирует.
Выход? Выделять память динамически. Ты убрал юникод из функции - да, это тебе не нужно. Но советую вернуть назад динамическое выделение памяти, без него передавать что-либо в другой поток не советую. В моих функциях память выделялась динамически и передавался указатель на выделенный буфер, который затем освобождался функцией в фоновом потоке.
Еще один момент - плагин у юзера необязательно будет называться "net", имя можно дать любое в настройке FS-плагинов.
Кстати, заметил, что у меня может теряться память, если будет ошибка создания фонового потока. Модернизировал:
Code: | struct BackgroundSendDataData {
COPYDATASTRUCT CopyData;
char Raw[0];
};
DWORD __stdcall BackgroundSendData(void* Data) {
BackgroundSendDataData* bsd=(BackgroundSendDataData*)Data;
auto_ptr<char> ash((char*)Data);
SendMessage(hMainWnd, WM_COPYDATA, 0, (LPARAM)&bsd->CopyData);
return 0;
}
bool ChangeCurrentDir(const wchar_t* Path, bool NewTab) {
int length=lstrlen(Path);
auto_ptr<char> ash(new char[sizeof(BackgroundSendDataData)+20+2*length]);
BackgroundSendDataData* bsd=(BackgroundSendDataData*)ash.get();
bsd->CopyData.dwData='DC';
bsd->CopyData.lpData=bsd->Raw;
char* p=bsd->Raw;
if (Unicode) p+=wsprintfA(p, "\xEF\xBB\xBF");
p+=WideCharToMultiByte(Unicode ? CP_UTF8 : CP_ACP, 0, Path, length, p, 2*length, 0, 0);
p+=wsprintfA(p, "\r%cS%s", 0, NewTab ? "T" : "");
bsd->CopyData.cbData=p-bsd->Raw+1;
HANDLE thread=CreateThread(0, 0, &BackgroundSendData, ash.get(), 0, 0);
if (!thread) return 0;
ash.release();
CloseHandle(thread);
return 1;
} |
(заодно сделал структуру буфера более понятной - вначале идет COPYDATASTRUCT, а сразу за ней - буфер произвольной длины, адрес и размер которого она содержит)
И ANSI-версия ChangeCurrentDir (вроде так, проверить нет времени; функция фонового потока общая):
Code: | bool ChangeCurrentDir(const char* Path, bool NewTab) {
int length=lstrlen(Path);
auto_ptr<char> ash(new char[sizeof(BackgroundSendDataData)+20+length]);
BackgroundSendDataData* bsd=(BackgroundSendDataData*)ash.get();
bsd->CopyData.dwData='DC';
bsd->CopyData.lpData=bsd->Raw;
char* p=bsd->Raw;
p+=wsprintf(p, "%s\r%cS%s", Path, length, 0, NewTab ? "T" : "");
bsd->CopyData.cbData=p-bsd->Raw+1;
HANDLE thread=CreateThread(0, 0, &BackgroundSendData, ash.get(), 0, 0);
if (!thread) return 0;
ash.release();
CloseHandle(thread);
return 1;
} |
На оффтоп отвечать не буду, раз модераторы против. Хотя, могу в личку.
HankHank wrote: | При нахождении “в среде плагина” попытка ввести “cd \\< IP или имя>” не приводит к успеху – надо слегка подриххтовать логику. Ты, впрочем, об этом вскользь уже говорил. |
Заметил этот абзац - и возник вопрос. Ты вводишь команду для перехода в сетевую папку, находясь в папке плагина, и оно не работает (в ТК команда cd не работает в папках FS-плагинов; ты должен вручную реализовать обработку команды cd и изменить текущую папку - например, вызвав ChangeCurrentDir, как делает моя VirtualPanel), или ты пытаешься обойти хук с помощью команды cd (я говорил как раз об этом - не нужно блокировать команду cd, раз юзер пишет ее, у него есть на то причины), или же этот абзац тоже подразумевает установку текста командной строки и выполнение для смены папки (маловероятно, что ты имел в виду это, но вдруг)? _________________ TCFS2 + TCFS2Tools: Полноэкранный режим и многое другое (обсуждение)
WINCMD.RU: AskParam, CopyTree, NTLinks, Sudo, VirtualPanel… |
|