2

アプリケーションがユーザーを偽装した後、プリンターの DEVMODE 構造を取得する必要があります。これは、アーキテクチャが Windows のアーキテクチャと一致している限り、32 ビット OS で実行されている 32 ビット アプリケーションと一致している限り、正常に機能します。ただし、DocumentProperties への呼び出しは、Windows 10 でエラー コード: 5 (アクセスが拒否されました) で失敗するか、64 ビット OS で実行されているアプリケーションの 32 ビット バージョンでの偽装後に Windows 7 で RPC エラーで失敗します。残念ながら、他のレガシー アプリケーションとやり取りする必要があるため、顧客は私のアプリケーションの 64 ビット バージョンを実行できません。

この問題の回避策を知っている人はいますか?

この問題を示す小さなサンプル コードを次に示します。問題を確認するには、x86 アプリケーションとしてビルドし、64 ビット OS で実行する必要があります。

// DocumentPropertiesTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <string>
#include <iostream>
#include "Winspool.h"
#include "DocumentPropertiesTest.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// The one and only application object

CWinApp theApp;

using namespace std;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    int nRetCode = 0;

    HMODULE hModule = ::GetModuleHandle(NULL);

    if (hModule != NULL)
    {
        // initialize MFC and print and error on failure
        if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
        {
            // TODO: change error code to suit your needs
            _tprintf(_T("Fatal Error: MFC initialization failed\n"));
            nRetCode = 1;
        }
        else
        {
         wstring username;
         wstring domainName;
         wstring password;
         wstring printername;
         int lastError;

         cout << "Please specify a valid username: ";
         wcin >> username;
         cout << "Please specify the computer or domain name for the user. Use \".\" for this computer: ";
         wcin >> domainName;
         cout << "Please specify the users password: ";
         wcin >> password;
         cout << "Please give the printer name: ";
         wcin.ignore();
         getline (wcin, printername);

         HANDLE pHandle;
         HANDLE pPrinter;
         if (LogonUser(username.c_str(), domainName.c_str(), password.c_str(), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &pHandle) != 0)
         {
            if (ImpersonateLoggedOnUser(pHandle) != 0)
            {
               PRINTER_DEFAULTS printerDefaults;

               printerDefaults.pDatatype     = NULL;
               printerDefaults.pDevMode      = NULL;
               printerDefaults.DesiredAccess = PRINTER_ALL_ACCESS;

               if (::OpenPrinter((LPWSTR)(printername.c_str()), &pPrinter, NULL))
               {
                  int dSize = ::DocumentPropertiesW(NULL, pPrinter, (LPWSTR)(printername.c_str()), NULL, NULL, 0);
                  if (dSize > 0)
                  {
                  }
                  else
                  {
                     lastError = ::GetLastError();
                     cout << "Failed DocumentProperties with Error code: " << lastError << endl;
                  }
                  ::ClosePrinter(pPrinter);
               }
               else
               {
                  lastError = ::GetLastError();
                  cout << "Failed OpenPrinter with Error code: " << lastError << endl;
               }
               RevertToSelf();
            }
            else
            {
               lastError = ::GetLastError();
               cout << "Failed ImpersonateLogonUser with Error code: " << lastError << endl;
            }
         }
         else
         {
            lastError = ::GetLastError();
            cout << "Failed LogonUser with Error code: " << lastError << endl;
         }

         system("pause");
        }
    }
    else
    {
        // TODO: change error code to suit your needs
        _tprintf(_T("Fatal Error: GetModuleHandle failed\n"));
        nRetCode = 1;
    }

    return nRetCode;
}
4

0 に答える 0