diff --git a/win32ss/user/ntuser/callback.c b/win32ss/user/ntuser/callback.c index 151a2f12af9..42d50002d33 100644 --- a/win32ss/user/ntuser/callback.c +++ b/win32ss/user/ntuser/callback.c @@ -1208,27 +1208,26 @@ co_IntSetupOBM(VOID) IntCbFreeMemory(Argument); } +// +// Called from Kernel GDI sides, no UserLeave/EnterCo required. +// LRESULT APIENTRY co_UserCBClientPrinterThunk( PVOID pkt, INT InSize, PVOID pvOutData, INT OutSize ) { - ULONG ResultLength; - PVOID ResultPointer; NTSTATUS Status; - UserLeaveCo(); Status = KeUserModeCallback(USER32_CALLBACK_UMPD, - 0, - 0, - &ResultPointer, - &ResultLength); + pkt, + InSize, + pvOutData, + (PULONG)&OutSize); - UserEnterCo(); - if (!NT_SUCCESS(Status)) { ERR("User UMPD callback failed!\n"); + return 1; } return 0; diff --git a/win32ss/user/user32/misc/dllmain.c b/win32ss/user/user32/misc/dllmain.c index a7d0f098b49..6f43b9eeb6b 100644 --- a/win32ss/user/user32/misc/dllmain.c +++ b/win32ss/user/user32/misc/dllmain.c @@ -2,6 +2,23 @@ #include +#define MAX_USER_MODE_DRV_BUFFER 526 + +// +// UMPD Packet Header should match win32ss/include/ntumpd.h +// +typedef struct _UMPDPKTHEAD +{ + INT Size; + INT Index; + INT RetSize; + DWORD Reserved; + HUMPD humpd; + ULONG_PTR Buffer[]; +} UMPDPKTHEAD, *PUMPDPKTHEAD; + +INT WINAPI GdiPrinterThunk(PUMPDPKTHEAD,PVOID,INT); + WINE_DEFAULT_DEBUG_CHANNEL(user32); #define KEY_LENGTH 1024 @@ -667,6 +684,30 @@ NTSTATUS WINAPI User32CallLPKFromKernel(PVOID Arguments, ULONG ArgumentLength) NTSTATUS WINAPI User32CallUMPDFromKernel(PVOID Arguments, ULONG ArgumentLength) { - // = GdiPrinterThunk( , , ); - return ZwCallbackReturn(Arguments, ArgumentLength, STATUS_SUCCESS); + DWORD Buffer[MAX_USER_MODE_DRV_BUFFER]; + INT cbSize = 0; + NTSTATUS Status = STATUS_SUCCESS; + PUMPDPKTHEAD pkt, pktOut = NULL; + + pkt = (PUMPDPKTHEAD)Arguments; + + if ( pkt->RetSize <= sizeof(Buffer) ) + { + pktOut = (PUMPDPKTHEAD)Buffer; + + if ( (GdiPrinterThunk( pkt, pktOut, pkt->RetSize ) == GDI_ERROR) ) + { + pktOut = NULL; + Status = STATUS_UNSUCCESSFUL; + } + else + { + cbSize = pkt->RetSize; + } + } + else + { + Status = STATUS_NO_MEMORY; + } + return ZwCallbackReturn( pktOut, cbSize, Status ); }