Я все еще борется с крючками.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):
код выглядит следующим образом:
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);
}
Любые подсказки, комментарии или советы высоко ценят ...
Я не уверен, является ли эта проблема, но я не думаю, что вы должны использовать общий раздел в вашей DLL. Выполняется ли вызов SetWindowsHookEx? –
@HarryJohnston: Да, крючок получает возвращаемое значение. Все работает, за исключением того, что GetMsgProc не вызывается (и здесь мне нужно установить SetWindowLongPtr для подкласса элемента управления). Таким образом, функция GetMsgProc должна быть частью адресного пространства noptepads ... –
Возможно, блокнот делает что-то неожиданное? Вы пробовали его в любых других приложениях, например, в простой своей программе? –