• 控制除WORD外的打印份数


    要实现一个小功能:监视所有打印任务,使得每次只能打印一份

    思路:使用EnumJobs 函数枚举所有的打印任务,得到打印的份数,如果发现份数不是1就将任务删除

    其中要用SetJob把任务删除的话需要有一定的权限。如果打印机的句柄是自己打开的,由于OpenPrinter 函数第三个参数不好设置,

    因此决定用API hook的办法。截获 EndDocPrinter函数,在里面实现主要功能

    PS:蛋疼的WORD真是恶心,用EnumJobs获取的打印份数始终是1,不知道是怎么回事

    主要代码如下:

    EndDocPrinter.h
     1 #pragma once
     2 
     3 #include "stdafx.h"
     4 
     5 typedef
     6     BOOL (WINAPI * __pfnEndDocPrinter)(
     7     _In_  HANDLE hPrinter
     8     );
     9 
    10 BOOL WINAPI my_EndDocPrinter(
    11     _In_  HANDLE hPrinter
    12     );
    13 
    14 extern __pfnEndDocPrinter pfnEndDocPrinter;
    EndDocPrinter.cpp:
     1 #include "stdafx.h"
     2 #include <Winspool.h>
     3 
     4 BOOL WINAPI my_EndDocPrinter(
     5                       _In_  HANDLE hPrinter
     6                    )
     7 {
     8     BOOL ret = FALSE;
     9     DWORD cbNeeded = 0, cReturned = 0;
    10     DWORD actNeeded = 0;
    11     TCHAR szCopys[MAX_PATH];
    12     ret = EnumJobs(hPrinter, 0, 127, 2, NULL, 0, &cbNeeded, &cReturned);
    13     actNeeded = cbNeeded;
    14     JOB_INFO_2* print_job = new JOB_INFO_2[actNeeded];
    15     ret = EnumJobs(hPrinter, 0, 127, 2, (LPBYTE)print_job, actNeeded, &cbNeeded, &cReturned);
    16     for (int i = 0; i < cReturned; i++)
    17     {
    18         short num=print_job[i].pDevMode->dmCopies;
    19         if(num!=1)
    20         {
    21             SetJob(hPrinter, print_job[i].JobId,2,(LPBYTE)&(print_job[i]),JOB_CONTROL_DELETE);
    22         }
    23     }
    24 
    25     return pfnEndDocPrinter(hPrinter);
    26 }

    DllMain中还是用之前的inline HOOK:

     1 // dllmain.cpp : 定义 DLL 应用程序的入口点。
     2 #include "stdafx.h"
     3 
     4 
     5 __pfnEndDocPrinter pfnEndDocPrinter = (__pfnEndDocPrinter)GetProcAddress(GetModuleHandle(TEXT("Winspool.drv")), "EndDocPrinter"); 
     6 
     7 BOOL APIENTRY DllMain( HMODULE hModule,
     8                        DWORD  ul_reason_for_call,
     9                        LPVOID lpReserved
    10                      )
    11 {
    12     switch (ul_reason_for_call)
    13     {
    14     case DLL_PROCESS_ATTACH:
    15         InlineHook(
    16             (__pfnEndDocPrinter)GetProcAddress(GetModuleHandle(TEXT("Winspool.drv")), "EndDocPrinter"),
    17             my_EndDocPrinter,
    18             (void **)&pfnEndDocPrinter
    19             );
    20     case DLL_THREAD_ATTACH:
    21     case DLL_THREAD_DETACH:
    22     case DLL_PROCESS_DETACH:
    23         break;
    24     }
    25     return TRUE;
    26 }
  • 相关阅读:
    WebAssembly API & MDN All In One
    Apple iPhone 14 Pro 药丸设计看不懂,药丸上面那条屏幕缝隙完全没有用处呀?
    API 调试工具 All In One
    macOS Time Machine All In One
    使用 macOS 输入多个空格,会自动添加一个点 bug All In One
    手把手的教你如何使用 Vite 搭建一个 React UI 组件库 All In One
    LeetCode 两数相加算法题解 All In One
    如何把 iPad 作为 Mac 扩展屏幕使用 All In One
    【DEMO】【C/C++】最简单的一种回调函数
    Qt中cvMat与QImage,QPixmap的转换
  • 原文地址:https://www.cnblogs.com/02xiaoma/p/2765295.html
Copyright © 2020-2023  润新知