サービスからリモート (共有) プリンターの印刷ジョブを監視したい。プリンターに接続するユーザー (例: \PC-PRINTER\Canon Printer) の偽装アクセス トークンがあります。
ユーザーとして偽装した後、OpenPrinter をプリンターに呼び出し、次に FindFirstPrinterChangeNotification を呼び出します。OpenPrinter は成功しましたが、FindFirstPrinterChangeNotification は ERROR_INVALID_HANDLE エラーで失敗しました。
通常のユーザー(サービスではなくプリンターの所有者)として試してみると、すべて成功し、通知が機能します。また、Windows XP で試してみると成功しましたが、Windows 7 とおそらく Windows Vista でのみ失敗しました。
偽装トークンのセキュリティ属性を設定するか、他の属性を OpenPrinter に渡す必要があると思います。私は多くのことを試しましたが、解決策が見つかりませんでした。
私のコード例:
PRINTER_NOTIFY_OPTIONS_TYPE optionsType;
unsigned short jobFields[] = {JOB_NOTIFY_FIELD_PRINTER_NAME};
optionsType.Type = JOB_NOTIFY_TYPE;
optionsType.Count = 1;
optionsType.pFields = &jobFields[0];
PRINTER_NOTIFY_OPTIONS options;
options.Version = 2;
options.Count = 1;
options.pTypes = &optionsType;
options.Flags = 0;
DWORD dwFilter = PRINTER_CHANGE_DELETE_JOB | PRINTER_CHANGE_SET_JOB ;
HANDLE hPrinterHandle = NULL;
ImpersonateLoggedOnUser(hUserToken); //I retrieve token from printer owner's process (I try every process for this user)
OpenPrinter(L"\\\\PC-PRINTER\\Canon Printer", &hPrinterHandle, NULL); \\it succeeded and I try many other parameters as well
HANDLE hNotification = FindFirstPrinterChangeNotification(hPrinterHandle, dwFilter, 0, (LPVOID) &options);
if (hNotification == INVALID_HANDLE_VALUE)
{//it comes here, GetLastError() == ERROR_INVALID_HANDLE (Windows 7, process runs as service)
//it succeded on Windows XP or when process runs in printer owner context
}
RevertToSelf();
解決策をありがとう!