0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PSA v4 Virtual Printer 実装調査: `PrintWorkflowVirtualPrinterSession.Start()` が `0x80070005` で拒否される件

0
Last updated at Posted at 2026-05-01

この記事は、PSA v4 Virtual Printer の完成済み実装手順ではありません。
Windows 11 24H2 / PSA v4 / MSIX / WinRT background task を使って仮想プリンター実装を検証した際に確認した、未解決の技術的問題と切り分け結果の共有です。

この記事の目的

Windows 11 24H2 以降の Windows Protected Print Mode を見据えて、Print Support App v4、いわゆる PSA v4 の Virtual Printer を使った仮想プリンター実装を検証しました。

公式ドキュメントと既存サンプルを参考に実装を進めましたが、最終的に PrintWorkflowVirtualPrinterSession.Start()0x80070005、つまり Access denied で失敗する境界に到達しました。

この記事では、以下を共有します。

  • どこまでは動いたか
  • どこで止まったか
  • 何を比較したか
  • どの仮説が弱くなったか
  • 現時点で疑っている trust / entitlement 境界
  • 同じ問題を調査する人向けの確認ポイント

この記事では、Microsoft の不具合と断定しません。
公開 API / 公開ログ / ローカル実装で確認できる範囲では説明しきれない Start() の認可拒否が残った、という整理です。

対象環境

検証した主な前提は次の通りです。

項目 内容
OS Windows 11 25H2
SDK Windows SDK 26100 系
実装形態 MSIX packaged app
Application Windows.FullTrustApplication
Capability runFullTrust
Printer driver Microsoft Virtual Print Class Driver
Workflow windows.printSupportVirtualPrinterWorkflow
Background task native in-process WinRT component
主な失敗点 PrintWorkflowVirtualPrinterSession.Start()
HRESULT 0x80070005
message アクセスが拒否されました。

参考にした資料

主に以下を参照しました。

また、Markdown 記法は Qiita のチートシートを参照しました。

最初に結論

現時点での観測結果は次です。

self-signed / sideloaded package では、
PrintWorkflowVirtualPrinterSession.Start() の broker 内部認可を
通過できない可能性がある。

少なくとも、今回の検証では以下を満たしても Start()0x80070005 で失敗しました。

  • virtual printer queue は作成される
  • background task は起動する
  • TriggerDetails は取得できる
  • VirtualPrinterSession は取得できる
  • VirtualPrinterDataAvailable handler は登録できる
  • runtime token は AppContainer token
  • token の AppContainer SID は VPM AppSid と一致
  • token の user SID は VPM UserSid と一致
  • PFN / AUMID も VPM PortData と一致
  • AppModel integrity check は成功する
  • Cube Minimal の PDC / PostScript 条件でも同じ失敗
  • OutputFileTypes="ps" 付き file-printer 形状でも同じ失敗

調査の流れ

大まかな流れは次の通りです。

到達したログ

native in-process background task 内で、次の地点まで到達しました。

NWF001 Run entered
NWF002 Deferral acquired
NWF003 TriggerDetails matched
NWF004 VirtualPrinterSession acquired
NWF005 VirtualPrinterDataAvailable handler registered
NWF005T Token diagnostics written
NWF005S Session.Start before call
NWF900 Run exception: HRESULT=0x80070005; message=アクセスが拒否されました。

重要なのは、Run() に入っていることです。
つまり、「background task が起動していない」問題ではありません。

さらに、VirtualPrinterSession も取れています。
そのため、「manifest の EntryPoint が解決できていない」「trigger details が違う」「session が取れない」といった段階も越えています。

失敗点は、かなり明確にここです。

m_session.Start();

token / VPM PortData の照合

Start() 直前で runtime token を採取し、Virtual Port Monitor の PortData と比較しました。

結果は次の通りです。

{
  "PackageFamilyNameMatches": true,
  "PackageFullNameMatches": true,
  "AumidMatches": true,
  "UserSidMatches": true,
  "AppContainerSidMatches": true
}

runtime token の例です。

tokenIsAppContainer   : true
tokenUserSid          : S-1-12-1-...
tokenAppContainerSid  : S-1-15-2-...

VPM PortData 側も同じ PFN / PFN full / AUMID / UserSid / AppSid を保持していました。

このため、少なくとも見える範囲では次の仮説は弱くなりました。

  • background task token に package SID が入っていない
  • VPM AppSid と token AppContainer SID が不一致
  • VPM UserSid と token user SID が不一致
  • PFN / AUMID がズレている
  • 通常の queue ACL / port ACL が違う

OneNote protected virtual printer との比較

実機にインストールされている OneNote protected virtual printer も比較しました。

OneNote 側は、おおむね次の形でした。

Application EntryPoint = Windows.FullTrustApplication
Capability = runFullTrust
windows.printSupportVirtualPrinterWorkflow
windows.activatableClass.inProcessServer
PreferredInputFormat = application/oxps
SupportedFormat = application/oxps MaxVersion=1.7
PDR なし
printSupportExtension なし

Custom 実装もこの形にかなり寄せました。

見える範囲の manifest / queue / PortData / ACL は近づけられましたが、Start() の拒否は変わりませんでした。

残った大きな差分は署名チェーンです。

対象 Signer Issuer
OneNote Microsoft Corporation Microsoft Marketplace Production CA 2011
Custom package CustomDocuCapture self-signed
Cube hybrid package CustomDocuCapture self-signed

Get-AppxPackage 上の SignatureKind だけでは差が見えませんでした。
しかし signtool verify /pa /v AppxSignature.p7x で見ると、OneNote は Microsoft Marketplace Production CA 由来、こちらの検証 package は self-signed でした。

Cube PSA sample との比較

Cube Soft さんの PSA v4 sample も参考にしました。

Cube sample は、PSA v4 Virtual Printer 実装の貴重な参考資料です。特に次の点が役立ちます。

  • DisplayName を PRI resource にする
  • PrinterUri を明示する
  • PreferredInputFormat / SupportedFormat を指定する
  • MSIX packaging を手動で行う
  • WinRT component の配置に注意する
  • printSupportExtension を含む形がある
  • PDC の最小構成を参考にできる

ただし、こちらの環境では C# / CsWinRT diagnostic build が 0x80040150 で background task activation に失敗し、Start() まで到達できませんでした。

そこで、Cube Minimal の manifest / PDC / PostScript 条件を残しつつ、background task だけを native in-process task に置き換えた hybrid package を作りました。

Cube manifest / PDC + native task hybrid

hybrid package の条件です。

Package identity       : CubePsaMinimalNativeDiag
PrinterName            : Cube PSA v4 Minimal Native Diag
PrinterUri             : cube-psa-minimal-native-diag:ps-printer
PDC                    : Cube Minimal の Printer.pdc
PreferredInputFormat   : application/postscript
SupportedFormat        : application/postscript
PDR                    : なし
Workflow task          : native in-process task
Extension task         : native in-process task
InProcessServer        : native task DLL

queue は作成されました。

Driver : Microsoft Virtual Print Class Driver
Port   : CubePsaMinimalNativeDiag_..._cube-psa-minimal-native-diag:ps-printer_...

XPS writer probe では、workflow task が起動し、Start() 直前まで到達しました。

NPE001 Extension Run entered
NPE002 Extension deferral acquired
NPE003 PrintSupportExtensionTriggerDetails matched
NPE004 PrintTicketValidationRequested handler registered
NPE005 Extension Session.Start called
NWF001 Run entered
NWF002 Deferral acquired
NWF003 TriggerDetails matched
NWF004 VirtualPrinterSession acquired
NWF005 VirtualPrinterDataAvailable handler registered
NWF005T Token diagnostics written
NWF005S Session.Start before call
NWF900 Run exception: HRESULT=0x80070005; message=アクセスが拒否されました。

つまり、Cube 条件に寄せても Start() で拒否されました。

RAW PostScript 経路でも同じ

Cube Minimal は application/postscript 条件なので、Win32 OpenPrinter / StartDocPrinter による RAW PostScript 投入も試しました。

結果として、RAW 経路でも workflow task は起動し、同じく Start() 直前で失敗しました。

NWF001 Run entered
NWF002 Deferral acquired
NWF003 TriggerDetails matched
NWF004 VirtualPrinterSession acquired
NWF005 VirtualPrinterDataAvailable handler registered
NWF005T Token diagnostics written
NWF005S Session.Start before call
NWF900 Run exception: HRESULT=0x80070005; message=アクセスが拒否されました。

これにより、XPS writer 経路だけの問題とも言いにくくなりました。

OutputFileTypes 付き file-printer 形状も試した

公式の説明では、OutputFileTypes を指定すると file printer として扱われると説明されています。
そこで、次の仮説を検証しました。

非 Microsoft package では OneNote 型の app/cloud 受け渡しは拒否されるが、
OutputFileTypes 付き file-printer なら Start() が通るのではないか。

追加した variant は次です。

PackageName      : CubePsaMinimalNativeDiagFile
PrinterName      : Cube PSA v4 Minimal Native Diag File
PrinterUri       : cube-psa-minimal-native-diag-file:ps-printer
OutputFileTypes  : ps
PreferredInput   : application/postscript
PDC              : Cube Minimal
Native task      : native in-process task

結果は同じでした。

NPE001 Extension Run entered
NPE005 Extension Session.Start called
NWF001 Run entered
NWF002 Deferral acquired
NWF003 TriggerDetails matched
NWF004 VirtualPrinterSession acquired
NWF005 VirtualPrinterDataAvailable handler registered
NWF005T Token diagnostics written
NWF005S Session.Start before call
NWF900 Run exception: HRESULT=0x80070005; message=アクセスが拒否されました。

つまり、OutputFileTypes="ps" を付けても Start() は拒否されました。

この結果により、「Save As 型なら回避できる」という仮説も弱くなりました。

ETW で見えたもの、見えなかったもの

以下の provider を採取しました。

Microsoft-Windows-PrintService
Microsoft-Windows-Graphics-Printing
Microsoft-Windows-AppModel-Runtime
Microsoft-Windows-BrokerInfrastructure
Microsoft-Windows-AppXDeployment-Server

見えたものです。

BrokerInfrastructure background task activation / unbuffer
AppModel integrity check
App integrity check finished with 0

見えなかったものです。

PrintWorkflowVirtualPrinterSession.Start() 内部での access check 理由
どの証明書 / publisher / entitlement / package policy を見て拒否したか

公開 provider の範囲では、Start() がなぜ access denied になったかまでは確認できませんでした。

現時点で弱くなった仮説

今回の調査で、以下は主因としてかなり弱くなりました。

仮説 弱くなった理由
Custom 固有の PDC 差分 Cube Minimal PDC でも同じ失敗
OXPS 条件が悪い PostScript 条件でも同じ失敗
printSupportExtension が必要 ありでも同じ失敗
OutputFileTypes が必要 ありでも同じ失敗
C# / CsWinRT activation 問題 native task で Start() まで到達
VPM / token SID mismatch SID / PFN / AUMID は一致
AppX 署名検証失敗 AppModel integrity check は成功
通常 ACL / port ACL OneNote 比較で差が見えない

現時点で残る仮説

現時点で残っている主な仮説は次です。

PrintWorkflowVirtualPrinterSession.Start() の内部で、
Microsoft Marketplace / Store / protected virtual printer entitlement 相当の
公開仕様に現れていない認可条件が確認されている可能性。

より具体的には、以下です。

  • Microsoft-signed package だけ許可される path がある
  • Store-signed package でないと許可されない
  • Partner Center 側で何らかの entitlement が必要
  • protected virtual printer path に追加の許可条件がある
  • self-signed / sideloaded package は queue 作成まではできるが、Start() で拒否される

ここは未確認です。
Store-signed package で同一コードを検証できていないため、署名・Store・entitlement のどれが条件なのかはまだ切れていません。

同じ調査をする人向けチェックリスト

  • queue が作成されているか
  • Driver が Microsoft Virtual Print Class Driver
  • VPM PortData が現在の PFN / AUMID を指しているか
  • background task の Run() に入っているか
  • TriggerDetails が取得できているか
  • VirtualPrinterSession が取得できているか
  • VirtualPrinterDataAvailable handler 登録まで到達しているか
  • Start() 直前の token を採取したか
  • token AppContainer SID と VPM AppSid が一致しているか
  • token user SID と VPM UserSid が一致しているか
  • PFN / AUMID が一致しているか
  • Start() の HRESULT を記録したか
  • OutputFileTypes あり / なしを比較したか
  • OXPS / PostScript 条件を比較したか
  • Store-signed / sideloaded / self-signed の差を切れているか

最後に

PSA v4 Virtual Printer は、ドキュメント上は ISV が software printer を実装できる仕組みに見えます。
しかし、少なくとも今回の検証では、queue 作成や background task activation よりさらに奥に、PrintWorkflowVirtualPrinterSession.Start() の trust boundary が存在するように見えます。

ここまで切り分けても 0x80070005 の理由が公開ログから見えないため、同じ領域を調査する場合は、queue 作成成功だけを成功判定にしないほうがよさそうです。

この調査が、同じところで詰まっている人の切り分け材料になれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?