2013-05-19 5 views
2

Я все еще борется с крючками.SetWindowLongPtr return ERROR_ACCESS_DENIED

Моя цель:

  • Установите крюк в notepad.exe
  • Подкласс это (моя конечная цель заключается в создании подкласса Редактировать класс и показать содержимое в моем собственном окне)

Отказ от ответственности: Я знаю, что есть более легкие способы получить текст/содержание из блокнота, но это способ познакомиться с C, winapi, Subclassing и hooks.

Моя проблема в том, что SetWindowLongPtr всегда возвращает ошибку ERROR_ACCESS_DENIED (код 5).

22 мая 2013 года: Это исправлено! Проблема заключалась в том, что SetWindowLongPtr оказался не в том месте. Он должен находиться внутри функции GetMsgProc.

вопрос стал немного долго и неаккуратно, поэтому я переписал вопрос (с обновленным кодом)

Сейчас проблема заключается в том, что GetMsgProc является НЕ вызывается, когда цель notepad.exe. Если я изменю цель на simple.exe, GetMsgProc будет вызван и работает!

(Simple.exe только простой GUI):

Simple.exe

код выглядит следующим образом:

exe.cpp

#include <windows.h> 
#include "Resource.h" 
#include <stdlib.h> 
#include "stdafx.h" 
#include <strsafe.h> 

#include "C:\Users\Kristensen\Documents\Visual Studio 2012\Projects\Win32D\dll\dllHeader.h" 

//--------------------------------------------------------------------------- 
HWND hWnd; 

LRESULT CALLBACK DlgProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); 
//--------------------------------------------------------------------------- 
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
        LPSTR lpCmdLine, int nCmdShow) 
{ 
    DialogBox(hInstance, MAKEINTRESOURCE(IDD_DLGFIRST), 
     hWnd, reinterpret_cast<DLGPROC>(DlgProc)); 

    return FALSE; 
} 
//--------------------------------------------------------------------------- 
LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam) 
{ 
    switch(Msg) 
    { 
    case WM_INITDIALOG: 
     return TRUE; 

    case WM_COMMAND: 
     switch(wParam) 
     { 
     case IDOK: 
      hookNotepad(); 
      return TRUE; 
     case IDCANCEL: 
      removeHook(); 
      EndDialog(hWndDlg, 0); 
     } 
     break; 
    } 

    return FALSE; 
} 
//--------------------------------------------------------------------------- 

dllHeader .h

#ifdef DLLAPI 
    #else 
    #define DLLAPI extern "C" __declspec(dllimport) 
    #endif 
    DLLAPI bool hookNotepad(); 
    DLLAPI bool removeHook(); 

dll.cpp:

#include "stdafx.h" 
#include <windows.h> 
#define DLLAPI extern "C" __declspec(dllexport) 
#include "dllHeader.h" 

// shared variables 
#pragma data_seg("Shared") 
HHOOK g_hHook = NULL; // Hook for Notepad 
HWND npHWND = NULL; // Notepad handle 
#pragma data_seg() 
#pragma comment(linker, "/section:Shared,rws") 

// Forward references 
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) ; 
LRESULT CALLBACK NewWndProc(HWND Hwnd, UINT Message, WPARAM wParam, LPARAM lParam); 
//LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam) ; 


LONG OldWndProc; 
DWORD pid; 
HINSTANCE g_hInstDll = NULL; // DllMain entry (DLL_PROCESS_ATTACH) 
DWORD npThreadId = NULL; // Notepad thread ID 

LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) //Testing with CBTProc - same issues as with GetMsgProc. 
{ 
    //If I hook notepad.exe, I never get called. (silence) 

    //If I hook simple.exe, I get called (Beep beep!) 

    // make some noise 
    static DWORD dwTickKeep = 0; 
    if ((GetTickCount()-dwTickKeep)>300) 
    { dwTickKeep = GetTickCount(); 
    Beep(2000, 100); 
    } 

    //Subclassing...... 
    //For simple.exe: (working) 
    //HWND hwndEdit = ::FindWindowEx(npHWND,NULL,TEXT("WindowsForms10.RichEdit20W.app.0.2bf8098_r14_ad1"), NULL); 
    //For notepad.exe: (not working) 
    HWND hwndEdit = ::FindWindowEx(npHWND,NULL,TEXT("Edit"), NULL); 

    if (hwndEdit) 
    { 
     //Subclass it 
     OldWndProc = GetWindowLongPtr(hwndEdit, GWLP_WNDPROC); 
     SetWindowLongPtr(hwndEdit, GWL_WNDPROC, (LONG_PTR)NewWndProc); 
    } 
    return(CallNextHookEx(g_hHook, nCode, wParam, lParam)); 
} 

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) 
{ 
    switch (ul_reason_for_call) 
    { 
    case DLL_PROCESS_ATTACH: 
     g_hInstDll = hModule; 
     break; 

    case DLL_THREAD_ATTACH: 
    case DLL_THREAD_DETACH: 
    case DLL_PROCESS_DETACH: 
     break; 
    } 
    return TRUE; 
} 

bool hookNotepad() 
{ 
    // If target is running 
    // if (npHWND = FindWindow(NULL, TEXT("simpleGUI"))) 
    if (npHWND = FindWindow(TEXT("Notepad"), NULL)) 
    { 
     // Finds the ThreadID for target. We use this in SetWindowsHookEx 
     npThreadId = GetWindowThreadProcessId(npHWND, &pid); 

     // Sets the hook in target 
     g_hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hInstDll, npThreadId); 
     //g_hHook = SetWindowsHookEx(WH_CBT, CBTProc, g_hInstDll, npThreadId); 

     // If the hook succesed 
     if (g_hHook) 
     { 
      ////Add a menu in the notepad.exe, but not relevant for subclassing notepads edit class... 
      //HMENU hCurrent = GetMenu(npHWND); //Get the CURRENT menu of the window. 
      //HMENU hNew = CreateMenu(); //Create a new one. 
      //AppendMenu(hCurrent, MF_STRING | MF_POPUP, (unsigned int)hNew, TEXT("myMenu")); 
      //AppendMenu(hNew, MF_STRING, 2000, L"myButton"); //2000 is the ID of the new button. 
      //DrawMenuBar(npHWND); //redraw the Menu. 

      //Force a msg to the messagequeue, so that the hook function(GetMsgProc) gets called 
      PostThreadMessage(npThreadId, WM_NULL, 0, 0); 
      return 1; 
     } 
     return 0; 
    } 
    else 
     //Notepad is not running 
     return 0; 
} 

bool removeHook() 
{ 
    // Removes the hook 
    if (g_hHook != NULL) 
    { 
     UnhookWindowsHookEx(g_hHook); 
     g_hHook = NULL; 
    } 
    return 0; 
} 



LRESULT CALLBACK NewWndProc(HWND Hwnd, UINT Message, WPARAM wParam, LPARAM lParam) 
{ 
    //We should come here and should be able to read the text from the Edit class... 
    return CallWindowProc((WNDPROC)OldWndProc, Hwnd, Message, wParam, lParam); 
} 

Любые подсказки, комментарии или советы высоко ценят ...

+0

Я не уверен, является ли эта проблема, но я не думаю, что вы должны использовать общий раздел в вашей DLL. Выполняется ли вызов SetWindowsHookEx? –

+0

@HarryJohnston: Да, крючок получает возвращаемое значение. Все работает, за исключением того, что GetMsgProc не вызывается (и здесь мне нужно установить SetWindowLongPtr для подкласса элемента управления). Таким образом, функция GetMsgProc должна быть частью адресного пространства noptepads ... –

+1

Возможно, блокнот делает что-то неожиданное? Вы пробовали его в любых других приложениях, например, в простой своей программе? –

ответ

2

Есть 3 проблемы в вашем коде:

(1) Переменная HWND npHWND предназначена для совместного использования между хост-ехом и блокнотом-ехом, поэтому он должен быть размещен внутри блока доли сегмента данных. Это значение в настоящее время оценивается внутри вызова «hookNotepad» и существует только в host-exe. Эта проблема привела к тому, что дескриптор npHWND был нулевым в блокнот-exe, и поэтому вызов SetWindowLongPtr завершился неудачно.

(2) Существует 2 SetWindowLongPtr звонков, один из них является неправильным.То, что внутри GetMsgProc правильно, потому что оно будет выполнено внутри контекста блокнота-exe, когда установлен крюк. Удалите другой неправильный внутри hookNotepad.

(3) Даже если разрешены (1) и (2), окончательное поведение SetWindowLongPtr может быть не таким, как вы ожидали, поскольку основной элемент интерактивного интерфейса в блокнот-exe является встроенным элементом управления редактированием, а не основным рамное окно. Вы должны перечислить дочерние окна блокнота и подкласса только одно дочернее окно с классом Edit.

Редактировать # 1 - Добавить код индикатора звука для проверки активности ----------------------------------- -

Добавить этот блок кода внутри GetMsgProc

// make some noise 
static DWORD dwTickKeep = 0; 
if ((GetTickCount()-dwTickKeep)>300) 
{ dwTickKeep = GetTickCount(); 
    Beep(2000, 100); 
} 
+0

Спасибо за ваш ответ и ваши действительные баллы. GetMsgProc все еще не работает. Я попытался установить крючок в моей собственной простой программе, и я получу немного дальше. Если я пытаюсь подключить simple.exe, то вызывается GetMsgProc! Но если я добавлю функцию SetWindowLongPtr в функцию GetMsgProc (Этот: OldWndProc = SetWindowLongPtr (npHWND, GWLP_WNDPROC, (long) NewWndProc);) ............ продолжение следует .. ... –

+0

............ Я получаю сообщение об ошибке, как только моя мышь нависает над моим «simpleGUI». Программа зависает, и я получаю: «Необработанное исключение win32 произошло в simple.exe» Когда я отлаживаю эту ошибку, я получаю следующее: Необработанное исключение в 0x76881F45 (usp10.dll) в файле simple.exe: 0xC0000005: место записи нарушения доступа . 0x001C0FFC до сих пор статус: * Я до сих пор не могу получить GetMsgProc работать при подключении notepad.exe * это работает, если я подключить simple.exe программу * The SetWindowLongPtr дает нарушение прав доступа (в простой..exe) –

+1

Если DLL появляется в пространстве памяти блокнота, как вы указали, должен работать 'GetMsgProc'. «GetMsgProc» - очень занятое место, так как все сообщения направляются через него. Если вам нужно сделать указание на активность, оно должно быть простым и коротким, поскольку длительная операция, например MessageBox, может привести к заклиниванию цикла сообщений. См. Редактирование # 1 для звукового индикатора. – mfc

1

Вы должны сделать это в контексте крючковатым процесса. Функция hookNotepad() выполняется в другом процессе и, следовательно, ваша функция WndProc() находится в другом адресном пространстве.

+0

Спасибо, я думал, что делаю это уже (?) Когда я ввел свой DLL-файл (с помощью hookNotepad () в нем), я думал, что файл dll находится в блокноте. Прикрепленный файл screendump показывает, что файл dll загружается в блокнот, не так ли? Можете ли вы привести пример того, как вводить функцию hookNotepad() в правильное адресное пространство? –

+0

Он загружается в файл notepad.exe, но вы все еще вызываете SetWindowLongPtr() в hookNotepad(), который запущен в исполняемом исполняемом файле. Вам нужно вызвать SetWindowLongPtr() в контексте файла notepad.exe, который в этом случае может быть сделан в hook (который, как представляется, вы уже делаете в MsgProc). – Luke

+0

Проблема в том, что функция GetMsgProc никогда не вызывается. Я имею в виду, что параметр 2 SetWindowsHook - это GetMsgProc, который является указателем на процедуру hook. Эта процедура/функция должна вызываться, когда блокнот получает сообщение, отправленное в очередь сообщений (очередь сообщений в блокнотах), правильно? Поэтому любое сообщение в блокноте (например, WM_ACTIVATE) должно запускать функцию GetMsgProc ........ но это не –