Related
I am new to programming with the Win32 API, and have been trying to figure out why this application is not returning when I close the window.
#include <windows.h>
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
// Register window class
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = L"Window Class";
RegisterClass(&wc);
// Create window
HWND window = CreateWindowEx(
0,
wc.lpszClassName,
L"Window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
// Show window
ShowWindow(window, nShowCmd);
// Main Program Loop
MSG msg = {};
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, window, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
I stepped through the code with a debugger and saw that after destroying the window, the value of the message was WM_PAINT, and so the program was continuously looping, but I don't understand why WM_QUIT is not being posted.
By providing window as an argument to PeekMessage you are telling it you only want to retrieve messages posted or sent to that window.
But WM_QUIT is a thread message - it's not associated with any given window. To retrieve it you need to call PeekMessage with nullptr for the window filter.
In addition to Jonathan Potter's answer, your message loop should be using GetMessage() instead of PeekMessage():
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
GetMessage() blocks the calling thread until a message arrives, and returns FALSE when WM_QUIT is received and the hWnd parameter is NULL.
By using PeekMessage(), you are running a tight busy loop, and the contents of msg are indeterminate when PeekMessage() returns FALSE when no message is available.
I'm trying to create a basic minifilter driver using Microsoft examples (PassThough, minispy...), but my MfPreOperationCallback is not called. I tried different contexts (even if I'm not sure to understand how that works...). I tried the PassThrough example and it works very well and it is very similar to my code...
Here is my inf file and my code :
;
; KmdfMiniFilter.inf
;
[Version]
Signature = "$WINDOWS NT$"
Class = "ActivityMonitor"
ClassGuid = {b86dff51-a31e-4bac-b3cf-e8cfe75c9fc2}
Provider = %ProviderString%
DriverVer = 02/09/2017,1.0.0.0
CatalogFile = KmdfMiniFilter.cat
[DestinationDirs]
DefaultDestDir = 12
KmdfMiniFilter.DriverFiles = 12
[DefaultInstall]
OptionDesc = %ServiceDescription%
CopyFiles = KmdfMiniFilter.DriverFiles
[DefaultInstall.Services]
AddService = %ServiceName%,,KmdfMiniFilter.Service
[DefaultUninstall]
DelFiles = KmdfMiniFilter.DriverFiles
[DefaultUninstall.Services]
DelService = %ServiceName%,0x200
[KmdfMiniFilter.Service]
DisplayName = %ServiceName%
Description = %ServiceDescription%
ServiceBinary = %12%\%DriverName%.sys
Dependencies = "FltMgr"
ServiceType = 2 ; SERVICE_FILE_SYSTEM_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
LoadOrderGroup = "FSFilter Activity Monitor"
AddReg = KmdfMiniFilter.AddRegistry
[KmdfMiniFilter.AddRegistry]
HKR,,"DebugFlags",0x00010001 ,0x0
HKR,,"SupportedFeatures",0x00010001,0x3
HKR,"Instances","DefaultInstance",0x00000000,%DefaultInstance%
HKR,"Instances\"%Instance1.Name%,"Altitude",0x00000000,%Instance1.Altitude%
HKR,"Instances\"%Instance1.Name%,"Flags",0x00010001,%Instance1.Flags%
[KmdfMiniFilter.DriverFiles]
%DriverName%.sys
[SourceDisksFiles]
KmdfMiniFilter.sys = 1,,
[SourceDisksNames]
1 = %DiskId1%,,,
[Strings]
ProviderString = "GUIDONO"
ServiceDescription = "KmdfMiniFilter mini-filter driver"
ServiceName = "KmdfMiniFilter"
DriverName = "KmdfMiniFilter"
DiskId1 = "File Change Monitoring Device Installation Disk"
DefaultInstance = "KmdfMiniFilter Instance"
Instance1.Name = "KmdfMiniFilter Middle Instance"
Instance1.Altitude = "370000"
Instance1.Flags = 0x1 ; Suppress automatic attachments
Registration.c
/**
Filter registration information
*/
#pragma once
#include <fltKernel.h>
#include "MiniFilter.h"
// Callbacks : list of FLT_OPERATION_REGISTRATION structures, one for each type of I/O for which the minifilter
// registers preoperation and postoperation callback routines.
// The last element must be IRP_MJ_OPERATION_END
CONST FLT_OPERATION_REGISTRATION Callbacks[] =
{
{
IRP_MJ_CREATE,
0,
MfPreOperationCallback,
MfPostOperationCallback
},
{ IRP_MJ_OPERATION_END }
};
// Defines the minifilter context structure
typedef struct _MINIFILTER_TRANSACTION_CONTEXT {
ULONG Flags;
ULONG Count;
} MINIFILTER_TRANSACTION_CONTEXT, *PMINIFILTER_CONTEXT;
// Contexts : a context structure is used to register context types
const FLT_CONTEXT_REGISTRATION Contexts[] =
{
{
FLT_TRANSACTION_CONTEXT, // Context type
0, // Flags
MfDeleteTxfContext, // ContextCleanupCallback
sizeof(MINIFILTER_TRANSACTION_CONTEXT), // Size
'ypsM' // PoolTag
},
{
FLT_CONTEXT_END
}
};
// This defines what we want to filter with FltMgr
CONST FLT_REGISTRATION FilterRegistration =
{
sizeof(FLT_REGISTRATION), // Size
FLT_REGISTRATION_VERSION, // Version
0, // Flags
Contexts, // Contexts
Callbacks, // Callbacks
MfUnload, // FilterUnload
MfInstanceSetup, // InstanceSetup
MfInstanceQueryTeardown, // InstanceQueryTeardown
MfInstanceTeardownStart, // InstanceTeardownStart
MfInstanceTeardownComplete, // InstanceTeardownComplete
NULL, // GenerateFileName
NULL, // GenerateDestinationFileName
NULL, // NormalizeNameComponent
};
Driver.c
#include <ntifs.h>
#include <wdf.h>
#include "RegistrationData.h"
#include "MiniFilter.h"
// Global data
MINIFILTER_DATA MfData;
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(RegistryPath);
//DbgSetDebugFilterState(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, TRUE);
NTSTATUS status;
MfData.Driver = DriverObject;
// Registering the minifilter driver
status = FltRegisterFilter(DriverObject, &FilterRegistration, &MfData.Filter);
KdPrint(("MINIFILTER INIT\n"));
if (!NT_SUCCESS(status)) {
KdPrint(("MINIFILTER ERROR : FltRegisterFilter failed. Code 0x%x\n", status));
return STATUS_UNSUCCESSFUL;
}
status = FltStartFiltering(MfData.Filter);
if (!NT_SUCCESS(status)) {
KdPrint(("MINIFILTER ERROR : FltStartFiltering faild. Code 0x%x\n", status));
FltUnregisterFilter(MfData.Filter);
return STATUS_UNSUCCESSFUL;
}
KdPrint(("MINIFILTER is Filtering!\n"));
return status;
}
NTSTATUS MfUnload(_In_ FLT_FILTER_UNLOAD_FLAGS Flags)
{
UNREFERENCED_PARAMETER(Flags);
PAGED_CODE();
KdPrint(("MINIFILTER UNLOAD\n"));
FltUnregisterFilter(MfData.Filter);
return STATUS_SUCCESS;
}
NTSTATUS MfQueryTearDown(_In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags)
{
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
PAGED_CODE();
return STATUS_SUCCESS;
}
MiniFilter.h
#pragma once
#include <fltKernel.h>
typedef struct MINIFILTER_DATA {
PDRIVER_OBJECT Driver;
PFLT_FILTER Filter;
} MINIFILTER_DATA;
FLT_PREOP_CALLBACK_STATUS MfPreOperationCallback(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID *CompletionContext
);
FLT_POSTOP_CALLBACK_STATUS MfPostOperationCallback(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ PVOID CompletionContext,
_In_ FLT_POST_OPERATION_FLAGS Flags
);
NTSTATUS MfInstanceSetup(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_SETUP_FLAGS Flags,
_In_ DEVICE_TYPE VolumeDeviceType,
_In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType
);
NTSTATUS MfInstanceQueryTeardown (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
);
VOID MfInstanceTeardownStart (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
);
VOID MfInstanceTeardownComplete (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
);
VOID MfDeleteTxfContext(
_Inout_ PFLT_CONTEXT Context,
_In_ FLT_CONTEXT_TYPE ContextType
);
NTSTATUS MfUnload(
_In_ FLT_FILTER_UNLOAD_FLAGS Flags
);
NTSTATUS MfQueryTearDown(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
);
NTSTATUS MfInstanceQueryTeardown(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
);
MiniFilter.c
#include "MiniFilter.h"
FLT_PREOP_CALLBACK_STATUS MfPreOperationCallback(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID *CompletionContext
)
{
UNREFERENCED_PARAMETER(Data);
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
KdPrint(("MINIFILTER PreOperationCallback\n"));
return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
FLT_POSTOP_CALLBACK_STATUS MfPostOperationCallback(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ PVOID CompletionContext,
_In_ FLT_POST_OPERATION_FLAGS Flags
)
{
UNREFERENCED_PARAMETER(Data);
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
UNREFERENCED_PARAMETER(Flags);
KdPrint(("MINIFILTER PostOperationCallback\n"));
return FLT_POSTOP_FINISHED_PROCESSING;
}
VOID MfDeleteTxfContext(
_Inout_ PFLT_CONTEXT Context,
_In_ FLT_CONTEXT_TYPE ContextType
)
{
UNREFERENCED_PARAMETER(Context);
UNREFERENCED_PARAMETER(ContextType);
KdPrint(("MINIFILTER DeleteTxfContext\n"));
}
NTSTATUS
MfInstanceSetup (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_SETUP_FLAGS Flags,
_In_ DEVICE_TYPE VolumeDeviceType,
_In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
UNREFERENCED_PARAMETER( VolumeDeviceType );
UNREFERENCED_PARAMETER( VolumeFilesystemType );
PAGED_CODE();
KdPrint(("PassThrough!PtInstanceSetup: Entered\n") );
return STATUS_SUCCESS;
}
NTSTATUS
MfInstanceQueryTeardown (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
PAGED_CODE();
KdPrint(("PassThrough!PtInstanceQueryTeardown: Entered\n") );
return STATUS_SUCCESS;
}
VOID
MfInstanceTeardownStart (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
PAGED_CODE();
KdPrint(("PassThrough!PtInstanceTeardownStart: Entered\n") );
}
VOID
MfInstanceTeardownComplete (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
PAGED_CODE();
KdPrint(("PassThrough!PtInstanceTeardownComplete: Entered\n") );
}
Does anyone see what's going on ?
I solved my problem : I had the wrong flag in my inf file. The good one is 0x0 flag in order to attach the minifilter automatically to the different volumes.
Instance1.Flags = 0x1 ; Suppress automatic attachments
to
Instance1.Flags = 0x0 ; Automatic attachments
i am trying to hook the CreateProcess under cmd.exe.
i manage to inject the dll the the cmd process but after the injection the dll process detach message receive and i fail to hook the createprocess function call.
i am using easyhook.
my code:
#include <windows.h>
#include <Shlwapi.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#include <easyhook.h>
BOOL WINAPI myCreateProcess(
_In_opt_ LPCTSTR lpApplicationName,
_Inout_opt_ LPTSTR lpCommandLine,
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ BOOL bInheritHandles,
_In_ DWORD dwCreationFlags,
_In_opt_ LPVOID lpEnvironment,
_In_opt_ LPCTSTR lpCurrentDirectory,
_In_ LPSTARTUPINFO lpStartupInfo,
_Out_ LPPROCESS_INFORMATION lpProcessInformation
){
OutputDebugString(L"\n !!!!!! In CreateProcess HOOK\n !!!!!!!!");
return CreateProcessW(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCommandLine, lpStartupInfo, lpProcessInformation);
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
BOOL bErrorFlag = FALSE;
DWORD dwBytesToWrite = (DWORD)strlen(DataBuffer);
DWORD dwBytesWritten = 0;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
HOOK_TRACE_INFO hHook = { NULL }; // keep track of our hook
// Install the hook
NTSTATUS result = LhInstallHook(
GetProcAddress(GetModuleHandle(TEXT("kernel32")), "CreateProcessW"),
myCreateProcess,
NULL,
&hHook);
if (FAILED(result))
{
OutputDebugString(L"!!!!!!!!!!!FAIL!!!!!!!!");
return 1;
}
ULONG ACLEntries[1] = { 0 };
LhSetInclusiveACL(ACLEntries, 1, &hHook);
OutputDebugString(L"!!!!!!!!!!!!Injection Succeed!!!!!!!!!!!!");
break;
}
case DLL_THREAD_ATTACH:{
OutputDebugString(L"!!!!!!!!!!!!dll thread attach!!!!!!!!!!!!");
break;
}
case DLL_THREAD_DETACH:
{
OutputDebugString(L"!!!!!!!!!!!!dll thread Detach!!!!!!!!!!!!");
break;
}
case DLL_PROCESS_DETACH:
{
OutputDebugString(L"!!!!!!!!!!!!dll process Detach!!!!!!!!!!!!");
break;
}
}
}
i receive the "Injection Succeed" message and right after the "dll process Detach" message .
any ideas?
try changing :
LhSetInclusiveACL(ACLEntries, 1, &hHook);
to :
LhSetExclusiveACL(ACLEntries, 1, &hHook);
I tried to tested out a simple GDI+ program but could not initialize it. The GdiplusStartup returns 2 which means "invalid parameters". In debug mode, I can see GdiplusStartupInput startInput is initialized (GdiplusVersion=1 ....etc.) so it is not the problem.
#include <windows.h>
#include "resource.h"
#include <iostream>
#include <string>
#include <sstream>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")
BOOL CALLBACK DialogProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
.... some code here ....
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
GdiplusStartupInput startInput;
ULONG_PTR* gdiToken = 0;
Gdiplus::Status status = Gdiplus::GdiplusStartup(gdiToken, &startInput, NULL);
return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc);
}
Thanks
The first argument is wrong. The documentation describes it like this:
Pointer to a ULONG_PTR that receives a token.
But you are passing a null pointer. Change the code like so:
GdiplusStartupInput startInput; // use default constructor to initialize struct
ULONG_PTR gdiToken;
Gdiplus::Status status = Gdiplus::GdiplusStartup(&gdiToken, &startInput, NULL);
i've made a simple windows api program having the functions WinMain() and WinProc() , but i'm getting this error :
error C2440: '=' : cannot convert from 'LRESULT (__stdcall *)(HWND,UINT,LPARAM,WPARAM)' to 'WNDPROC'
1> This conversion requires a reinterpret_cast, a C-style cast or function-style cast
#include<windows.h>
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, LPARAM lParam, WPARAM wParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX WindowClass;
static LPCTSTR szAppName = L"OFWin";
HWND hWnd;
MSG msg;
WindowClass.cbSize = sizeof(WNDCLASSEX);
WindowClass.style = CS_HREDRAW | CS_VREDRAW;
WindowClass.lpfnWndProc = WindowProc; // error
....
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, LPARAM lParam, WPARAM wParam)
{ ..... }
the program's taken word to word from my book (ivor horton's beginning visual c++ 2010), what's wrong?
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, LPARAM lParam, WPARAM wParam);
Here's your problem: the LPARAM and WPARAM are backwards, it should be:
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
WPARAM and LPARAM have two different types (UINT_PTR and INT_PTR respectively - for historical reasons mostly), so you get a type related error if you accidentally swap them around. Which is a lucky thing in your case: if they were the same type, then instead of getting a compiler error, the code would compile fine, and you'd instead spend some time wondering why your wndproc was apparently getting mixed up parameters passed to it!