Добро пожаловать! Это — архивная версия форумов на «Хакер.Ru». Она работает в режиме read-only.
 

С++ Builder 6.0 - проблема с dll (с кодировками)

Пользователи, просматривающие топик: none

Зашли как: Guest
Все форумы >> [Компилируемые языки] >> С++ Builder 6.0 - проблема с dll (с кодировками)
Имя
Сообщение << Старые топики   Новые топики >>
С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-21 16:53:14.630000   
Zmaster

Сообщений: 930
Оценки: 0
Присоединился: 2007-02-09 19:02:43.500000
Привет народ! Имеетсся такая часть кода в dll(Это WH_CBT хук):

FILE *fil; LPCBTACTIVATESTRUCT wind; ........ int __stdcall CBTHook(int code, int wParam, int lParam) { char b[200]; if (fil==0) fil = fopen("D:\\GAMES\\file.txt","w"); if (code==HCBT_ACTIVATE) { wind = (LPCBTACTIVATESTRUCT)lParam; SendMessage(wind-&gt;hWndActive,WM_GETTEXT,sizeof(b),(LPARAM)(LPCTSTR)b); fputs(b,fil); } return CallNextHookEx(HKey1,code,wParam,lParam); }
При установке хука, должны записываться в файл file.txt все заголовки окон, которые активирует пользователь. Но в файл записываются какие-то "иероглифы", а то и вообще не записывается. Хотя если писать текст напрямую вот так:

fputs("привет",fil); то все хорошо пишется. В чем проблема? Подскажите, кто знает. (Если что непонятно - спрашивайте)
Post #: 1
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-21 19:18:36.740000   
tеstеr

Сообщений: 377
Оценки: -46
Присоединился: 2008-02-08 17:56:40.563333
к своему стыду впервые вижу хуки, но могу предположить, что

#ifdef UNICODE
typedef LPCWSTR LPCTSTR;
#else
typedef LPCSTR LPCTSTR;
#endif

Попробуй указать явно эти типы, или явно определи UNICODE
или замени
(LPARAM)(LPCTSTR)b
на
(LPARAM)(LPCSTR)b //для не юникод
(LPARAM)(LPCWSTR)b //для юникод
Сам же пишешь, что кодировка.
Соотвественно, емли у тебя все же
#ifdef UNICODE
то буфер сделай на 400 символов, а не на 200.

Открывай файл той прогой, которая любые кодировки тянет - Notepad++, например.

А может функция вызывается очень часто, и к файлу fil запросы сыплются валом, и отсюда ошибки.

Вот что прочитал
When the WM_GETTEXT message is sent to a static control with the SS_ICON style, a handle to the icon will be returned in the first four bytes of the buffer pointed to by lParam. This is true only if the WM_SETTEXT message has been used to set the icon.

Далее читаю
For a button, the text is the button name. For other windows, the text is the window title. To copy the text of an item in a list box, an application can use the LB_GETTEXT message.

Вот это самое то - шли другое сообщение - LB_GETTEXT

А самое лучшее - не слушай мой бред а используй отладчик.
Post #: 2
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-21 22:27:20.090000   
Zmaster

Сообщений: 930
Оценки: 0
Присоединился: 2007-02-09 19:02:43.500000
Спасибо tеstеr, буду пробовать, потом отпишусь.

Post #: 3
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-21 22:42:34.223333   
alexbozhko

Сообщений: 1024
Оценки: 0
Присоединился: 2005-11-24 13:35:34
Интересно прогнать этот код в Builder 2009 и посмотреть результат….
Post #: 4
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-23 15:02:07.446666   
Zmaster

Сообщений: 930
Оценки: 0
Присоединился: 2007-02-09 19:02:43.500000
tеstеr, не совсем получается, хук записывает в файл отчета только окна, связанные с самим билдером, например вот файл отчета, когда я активырую по очереди два окна билдера:

main.cpp C++Builder 6 - pril [Running] main.cpp C++Builder 6 - pril [Running] main.cpp

А вот файл отчета, когда я активирую окна программ, например, Калькулятор и блокнот:

ю €c €c ,э ~ыc
Кстати, может я как то не так ставвлю хук? Вот код установки хука, который располагается в той же dll:


HHOOK HKey1 = 0; ............................... void Start1() { HKey1 = SetWindowsHookEx(WH_CBT, (WNDENUMPROC)CBTHook, HInstance, 0); if (HKey1 == 0) ShowMessage("BAD1"); }
В чем может быть проблема?
Post #: 5
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-23 19:37:12.046666   
tеstеr

Сообщений: 377
Оценки: -46
Присоединился: 2008-02-08 17:56:40.563333
тут был дурацкий комент.
счас че нить умное напишу …
Post #: 6
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-24 01:27:17.966666   
_SaZ_

Сообщений: 4329
Оценки: 398
Присоединился: 2008-01-30 02:18:05.553333
SendMessageA попробуй, без дурацких приведений типов, вместо SendMessage… А лучше почитай про UNICODE
Post #: 7
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-24 15:46:45.790000   
Zmaster

Сообщений: 930
Оценки: 0
Присоединился: 2007-02-09 19:02:43.500000
_SaZ_, я попробовал эту функцию, результат один и тот же. Так же я пробовал функцию SendMessageW, но не получается:

SendMessageA(wind-&gt;hWndActive,WM_GETTEXT,sizeof(b),(LPARAM)b);
Но у меня вопрос, почему Билдеровские окна-то пишутся в файл, на каком языке они бы не были, а другие пишутся иероглифами? Может у билдера своя какая-то кодировка?

Кстати, про Юникод прочитал вот тут: http://ru.wikipedia.org/wiki/UNICODE

Я уже неделю по этому вопросу поисковики мучаю. С нетерпением жду ваших советов.
Post #: 8
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-25 01:47:04.523333   
tеstеr

Сообщений: 377
Оценки: -46
Присоединился: 2008-02-08 17:56:40.563333
Zmaster, вот этот твой код верный

FILE *fil; LPCBTACTIVATESTRUCT wind; ........ int __stdcall CBTHook(int code, int wParam, int lParam) { char b[200]; if (fil==0) fil = fopen("D:\\GAMES\\file.txt","w"); if (code==HCBT_ACTIVATE) { wind = (LPCBTACTIVATESTRUCT)lParam; SendMessage(wind-&gt;hWndActive,WM_GETTEXT,sizeof(b),(LPARAM)(LPCTSTR)b); fputs(b,fil); } return CallNextHookEx(HKey1,code,wParam,lParam); }
Я тоже пробовал сделать получение заголовков окна с SendMessage не получилось (

Попробуй вот такую фуцию:
int GetWindowText( HWND hWnd,
LPTSTR lpString,
int nMaxCount
);

Смотри её описание:
hWnd [in] Handle to the window or control containing the text.

lpString [out] Pointer to the buffer that will receive the text. If the string is as long or longer than the buffer, the string is truncated and terminated with a NULL character.

nMaxCount [in] Specifies the maximum number of characters to copy to the buffer, including the NULL character. If the text exceeds this limit, it is truncated.

If the target window is owned by the current process, GetWindowText causes a WM_GETTEXT message to be sent to the specified window or control. If the target window is owned by another process and has a caption, GetWindowText retrieves the window caption text. If the window does not have a caption, the return value is a null string. This behavior is by design. It allows applications to call GetWindowText without becoming unresponsive if the process that owns the target window is not responding. However, if the target window is not responding and it belongs to the calling application, GetWindowText will cause the calling application to become unresponsive.

Откуда видно, что WM_GETTEXT применяется для получения заголовков, только для окон текущего процесса. Для окон других процессов применяются другие способы.

==================================================
Вот другая функция, которая вытаскивает текст заголовка из памяти, а не с помощью сообщений (результат всегда в юникоде):

int InternalGetWindowText( HWND hWnd,
LPWSTR lpString,
int nMaxCount
);

This function is similar to the GetWindowText function. However, it obtains the window text directly from the window structure associated with the specified window's handle and then always provides the text as a unicode string. This is unlike GetWindowText which obtains the text by sending the window a WM_GETTEXT message. If the specified window is a control, the text of the control is obtained.

Поддерживается начиная с Windows 2000.

===============================================
Вот, что Рихтер пишет про работу функции SendMessage (почему она не всегда работает для окон, принадлежащих другим проецссам).
===============================================

Вот как работает SendMessage. Если поток вызывает SendMessage для посылки со-
общения окну, созданному им же, то функция просто обращается к оконной процедуре соответствующего окна как к подпрограмме. Закончив обработку, оконная процедура передает функции SendMessage некое значение, а та возвращает его вызвавшему потоку.

Однако, если поток посылает сообщение окну, созданному другим потоком, операции, выполняемые функцией SendMessage, значительно усложняются. Windows требует, чтобы оконное сообщение обрабатывалось потоком, создавшим окно. Поэтому, если вызвать SendMessage для отправки сообщения окну, созданному в другом процессе и, естественно, другим потоком, Ваш поток не сможет обработать это сообщение — ведь он не работает в адресном пространстве чужого процесса, а потому не имеет доступа к коду и данным соответствующей оконной процедуры. И действительно, Ваш поток приостанавливается, пока другой поток обрабатывает сообщение. Поэтому, чтобы один поток мог отправить сообщение окну, созданному другим потоком, система должна выполнить следующие действия.

Во-первых, переданное сообщение присоединяется к очереди сообщений потока-приемника, в результате чего для этого потока устанавливается флаг QS_SENDMESSAGE. Во-вторых, если поток-приемник в данный момент выполняет какой-то код и не ожидает сообщений (через вызов GetMessage, PeekMessage или WaitMessage), переданное сообщение обработать не удастся — система не прервет работу потока для немедленной обработки сообщения. Но когда поток-приемник ждет сообщений, система сначала проверяет, установлен ли флаг пробуждения QS_SENDMESSAGE, и, если да, просматривает очередь синхронных сообщений, отыскивая первое из них. В очереди может находиться более одного сообщения. Скажем, несколько потоков одновременно послали сообщение одному и тому же окну. Тогда система просто ставит эти сообщения в очередь синхронных сообщений потока.

Итак, когда поток ждет сообщений, система извлекает из очереди синхронных сообщений первое и вызывает для его обработки нужную оконную процедуру. Если таких сообщений больше нет, флаг QS_SENDMESSAGE сбрасывается. Пока поток-приемник обрабатывает сообщение, поток, отправивший сообщение через SendMessage, простаивает, ожидая появления сообщения в очереди ответных сообщений. По окончании обработки значение, возвращенное оконной процедурой, передается асинхронно в очередь ответных сообщений потока-отправителя. Теперь он пробудится и извлечет упомянутое значение из ответного сообщения. Именно это значение и будет результатом вызова SendMessage. С этого момента поток-отправитель возобновляет работу в обычном режиме.
Post #: 9
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-25 12:58:45.433333   
Zmaster

Сообщений: 930
Оценки: 0
Присоединился: 2007-02-09 19:02:43.500000
Щаз попробую, скоро отпишусь.
Post #: 10
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-25 14:18:20.073333   
Zmaster

Сообщений: 930
Оценки: 0
Присоединился: 2007-02-09 19:02:43.500000
tester, посмотри, вот код:


HMODULE hUser32; typedef BOOL (WINAPI *PROCINTERNALGETWINDOWTEXT)(HWND,LPWSTR,int); PROCINTERNALGETWINDOWTEXT InternalGetWindowText; HHOOK HKey1 = 0; FILE *fil; LPCBTACTIVATESTRUCT wind; .......................................... int __stdcall CBTHook(int code, WPARAM wParam, LPARAM lParam) { char b[400]; if (fil==0) fil = fopen("D:\\GAMES\\file.txt","w"); if (code&gt;=0 && code==HCBT_ACTIVATE) { wind = (LPCBTACTIVATESTRUCT)lParam; InternalGetWindowText(wind-&gt;hWndActive,(LPWSTR)b,sizeof(b)); fputs( (AnsiString(b)+'\n').c_str() ,fil); } return CallNextHookEx(HKey1,code,wParam,lParam); } void Start1() //утановка хука { hUser32 = GetModuleHandle("user32"); InternalGetWindowText =(PROCINTERNALGETWINDOWTEXT)GetProcAddress(hUser32,"InternalGetWindowText"); HKey1 = SetWindowsHookEx(WH_CBT, (WNDENUMPROC)CBTHook, HInstance, 0); if (HKey1 == 0) ShowMessage("BAD1"); }
Пришлось грузить библиотеку динамически, т.к. разработчики скрыли функцию InternalGetWindowText. Вобщем у меня не совсем получается, так как после установки хука сразу слетает explorer.exe, все виснет, винда издает странные звуки, и в винампе играет lostprophets:). В чем проблема? Я поискал про эту функцию в нете, зделал, как там советовали. Может я как-то не так подгружаю библиотеку?
Post #: 11
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-25 14:46:00.836666   
tеstеr

Сообщений: 377
Оценки: -46
Присоединился: 2008-02-08 17:56:40.563333
Про юникод и строку "InternalGetWindowText(wind->hWndActive,(LPWSTR)b,sizeof(b));"
в юникоде символ = 2 байта.
значит если ты передал (LPWSTR)b на 400 байт,
то максимальная длина строки - 200 символов, т.е. sizeof(b)/2.

Про зависание
наверно причина в строке fputs( (AnsiString(b)+'\n').c_str() ,fil);
1) конвертация в AnsiString - создание класса, ….
2) сложение двух строк - тоже не просто
3) вызов метода c_str() - это тоже новое выделение памяти
4) потом зыпись строки в файл
5) уничтожение класса AnsiString

Сделай вывод результата попроще (пошустрее):
TextOutW(hdc, 10, 10, (LPCSTR)b, 200);
Если будет работать (будет выдавать заголовки окон на главном окне), то значит все нормально.

=================
Вот по этой строке вопрос:
HKey1 = SetWindowsHookEx(WH_CBT, (WNDENUMPROC)CBTHook, HInstance, 0);

HInstance - указывает на длл-ку? или на приложение?
Должно быть так (если что):
HInstance = LoadLibrary((LPCTSTR) "библиотека_с_хуком.dll");

А по теме, у меня ничего не получилось с хуками
=================
Вот код которым я тестил.
Хуки ставил на текущий поток, сообветсвенно, переменная int test увеличивалась, только при активации текущего окна.
С Длл-кой я не пробовал.
HHOOK hhook; HWND hwndMain; CHAR b2[100]; int test=0; LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam) { HDC hdc; if ((nCode &gt;= 0)&&(nCode==HCBT_ACTIVATE)) { wsprintf(b2, "%d %d %d %d", nCode, wParam, lParam, test++); hdc = GetDC(hwndMain); TextOutA(hdc, 2, 175, (CHAR *)b2, strlen(b2)); ReleaseDC(hwndMain, hdc); } return CallNextHookEx(hhook, nCode, wParam, lParam); } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; TCHAR buf[4]; switch (message) { case WM_CREATE: hwndMain = hWnd; hhook = SetWindowsHookEx( WH_CBT,CBTProc, (HINSTANCE) 0, GetCurrentThreadId()); if (hhook == 0) { wsprintf(buf, "bad"); MessageBox(0, buf, buf, MB_OK); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); TextOutA(hdc, 2, 175, (CHAR *)b2, strlen(b2)); EndPaint(hWnd, &ps); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
Post #: 12
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-26 15:12:13.223333   
Zmaster

Сообщений: 930
Оценки: 0
Присоединился: 2007-02-09 19:02:43.500000
И он не работает?
И что же теперь делать?
Post #: 13
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-26 15:47:08.476666   
_SaZ_

Сообщений: 4329
Оценки: 398
Присоединился: 2008-01-30 02:18:05.553333
Моё мнение, что вышеприведенный код даже не скомпилится… не говоря уже про работоспособность. Опять же - про юникод может ты и почитал, но как с ним работать - нифига не понял.

Копни файлик TCHAR.H, а ещё лучше компилируй без юникода и будет тебе Щастье.
Post #: 14
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-26 17:21:33.656666   
Zmaster

Сообщений: 930
Оценки: 0
Присоединился: 2007-02-09 19:02:43.500000

quote:

ORIGINAL: _SaZ_

Моё мнение, что вышеприведенный код даже не скомпилится… не говоря уже про работоспособность. Опять же - про юникод может ты и почитал, но как с ним работать - нифига не понял.

Копни файлик TCHAR.H, а ещё лучше компилируй без юникода и будет тебе Щастье.

Ты думаешь, что проблема с юникодом? Мне кажется, что все дело в потоках.
Post #: 15
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-26 19:03:16.893333   
Zmaster

Сообщений: 930
Оценки: 0
Присоединился: 2007-02-09 19:02:43.500000
Я попробовал использовать функцию InternalGetWindowText в отдельном приложении, где нет всякого мусора, вобщем компилится и линкуется все хорошо, но во время выполнения возникает ошибка, типа программа обратилась к той памяти, в которую ей лезть нельзя. Вобщем я так понял эта функция у меня из dll доставаться не хочет. Вот…
Post #: 16
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-27 07:44:03.766666   
Zmaster

Сообщений: 930
Оценки: 0
Присоединился: 2007-02-09 19:02:43.500000
up
Post #: 17
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-27 12:34:32.196666   
_SaZ_

Сообщений: 4329
Оценки: 398
Присоединился: 2008-01-30 02:18:05.553333
Мне кажется, что дело в руках ;) и нежелании разбираться.
Post #: 18
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-27 14:07:59.756666   
Zmaster

Сообщений: 930
Оценки: 0
Присоединился: 2007-02-09 19:02:43.500000

quote:

ORIGINAL: _SaZ_

Мне кажется, что дело в руках ;) и нежелании разбираться.

Ты ошибаешься
Post #: 19
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-27 15:18:28.146666   
_SaZ_

Сообщений: 4329
Оценки: 398
Присоединился: 2008-01-30 02:18:05.553333
Потоки ни при чём. Но SendMessage использовать не стоит, чтобы не задэдлочить свой поток.
Post #: 20
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-27 17:03:15.533333   
Zmaster

Сообщений: 930
Оценки: 0
Присоединился: 2007-02-09 19:02:43.500000

quote:

ORIGINAL: _SaZ_

Потоки ни при чём. Но SendMessage использовать не стоит, чтобы не задэдлочить свой поток.

понятно, главное теперь знаю, что потоки ни при чем.
Post #: 21
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-28 15:04:04.176666   
_SaZ_

Сообщений: 4329
Оценки: 398
Присоединился: 2008-01-30 02:18:05.553333
Да, очищай буфер (забивай нулями, собачками или-чем-нить специфическим). Может у тебя туда вообще ничего не помещается, а в файл пишется лишь мусор, который до этого был в куче.
Post #: 22
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-29 15:13:54.926666   
Zmaster

Сообщений: 930
Оценки: 0
Присоединился: 2007-02-09 19:02:43.500000
Я хочу попробовать с помощью функции InternalGetWindowText(). В простом приложении у меня это получилось, оказывается надо просто выделять память так:
WCHAR buf=new WCHAR[200]; и тогда все получается. Но когда я это использую в dll, у меня или слетает эксплорер или закрывается приложение, которое акривирую. Мне кажется генереруется какое либо программное исключение.
Вот код:
 
typedef bool (WINAPI *PROCINTERNALGETWINDOWTEXT)(HWND,LPWSTR,int); PROCINTERNALGETWINDOWTEXT InternalGetWindowText; &nbsp; WCHAR*&nbsp; wCaption; HHOOK HKey1 = 0; FILE *fil; HMODULE hUser32; LPCBTACTIVATESTRUCT&nbsp; wind; &nbsp; .................................. &nbsp; int __stdcall CBTHook(int code, WPARAM wParam, LPARAM lParam)&nbsp;&nbsp; //функция хука { if (fil==0) fil = fopen("D:\\GAMES\\file.txt","w"); if (code&gt;=0 &amp;&amp; code==HCBT_ACTIVATE) { &nbsp;wind = (LPCBTACTIVATESTRUCT)lParam; &nbsp;InternalGetWindowText(wind-&gt;hWndActive,wCaption,sizeof(WCHAR)*200); &nbsp;fputs(AnsiString(wCaption).c_str(),fil); } return CallNextHookEx(HKey1,code,wParam,lParam); } &nbsp; ........................... &nbsp; void Start1()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //установка хука. { wCaption=new WCHAR[200]; hUser32 = GetModuleHandle("user32"); InternalGetWindowText = (PROCINTERNALGETWINDOWTEXT)GetProcAddress(hUser32,"InternalGetWindowText"); HKey1 = SetWindowsHookEx(WH_CBT, (WNDENUMPROC)CBTHook, HInstance, 0); if (HKey1 == 0) ShowMessage("BAD1"); }
Post #: 23
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-29 15:47:58.190000   
_SaZ_

Сообщений: 4329
Оценки: 398
Присоединился: 2008-01-30 02:18:05.553333
AnsiString - что это?! Человек, уже кричу (выше просто писал) - РАЗБЕРИСЬ С ЮНИКОДОМ.

Да и статическая линковка нынче не в моде?

И убей на… свой InternalGetWindowText. Используй человеческие GetWindowTextLength + GetWindowText.
http://msdn.microsoft.com/en-us/library/ms633523.aspx

Кстати, в SetWindowHookEx чему у тебя равен hInstance?
Post #: 24
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-01-31 21:51:35.180000   
Zmaster

Сообщений: 930
Оценки: 0
Присоединился: 2007-02-09 19:02:43.500000
Ладно ребят, спасибо за помощь дальше думаю сам разберусь, а то как то не хорошо получается, _SaZ_ , и tеstеr ++. Спасибо.
Post #: 25
RE: С++ Builder 6.0 - проблема с dll (с кодировками) - 2009-02-02 02:45:38.733333   
_SaZ_

Сообщений: 4329
Оценки: 398
Присоединился: 2008-01-30 02:18:05.553333
Кури в сторону hInstance. Туда скорее всего нужно сувать инстанс приложения, к которому аттачишь длл, а не инстанс твоей длл.
Post #: 26
Страниц:  [1]
Все форумы >> [Компилируемые языки] >> С++ Builder 6.0 - проблема с dll (с кодировками)







Связаться:
Вопросы по сайту / xakep@glc.ru

Предупреждение: использование полученных знаний в противозаконных целях преследуется по закону.