公式の配布物
受け入れたversionとhashを照合し、未検証の更新へ自動追従しない。
PASS / vendor channelCase note 2026-07Windowsゲームランチャー · 起動・認証 · Electron / WineStatus: closed with open boundary
Windows向けゲーム配信ランチャーが起動直後に落ちる。修正すると窓は残るが中身が黒い。 画面が見えてもブラウザ認証から戻れるとは限らず、そこから起動したゲームには別のruntimeが要る。 一つの「動かない」をprocessと責務の境界へ分け、公式clientとゲーム本体を変更せず閉じた記録である。
標準読者は、Wineとprefixの基礎を知り、Windows向けランチャーの互換性を自分で調べたい技術者である。この記事の目標は、processが生きたことを「動いた」とせず、次の6条件を別々に判定できるようになることだ。
受け入れたversionとhashを照合し、未検証の更新へ自動追従しない。
PASS / vendor channelWindows installerを完走させず、検証済みpayloadだけをprefixへ安全に配置する。
PASS / transactional不足関数の候補ではなく、crashしたimport slotまで結んで必要APIを特定する。
PASS / upstream backportwindowの存在とcontentの描画を分け、swapchainとpresentの実callを確認する。
PASS / same processMac側がcustom URL schemeを受け、同じprefixとruntimeへ戻す。
PARTIAL / fresh session open配信clientの描画と、そこから起動する32-bitゲームのfontや動画環境を分ける。
PASS / 2 canaries検証対象は、ChromiumとNode.jsを同梱するデスクトップアプリ基盤(Electron)で作られたx64 Windows clientだった。同じ配布面には過去のJava系clientも存在したが、別binaryの知見を現行clientへ持ち込むと、調べるruntimeもfailure surfaceもずれる。
入口にはなるが、architectureやframeworkの根拠にはしない。
PE architecture、version、framework、delay importを実体から確認する。
browser、GPU、renderer、child gameの所有関係を分ける。
Windows installerのGUIは、PowerShellを使う「既存アプリ終了」確認で停止した。そこでinstallerを無理に完走させず、公式metadataから固定した配布物をMac側で検証し、Windows installer形式(NSIS)の最終payloadだけをmacOS標準の展開器で取り出した。
01 — PIN
公式metadataのsizeとSHA-512に、Mac側で計算したSHA-256を加える。どれか一つでも違えば配置しない。
最新版へ追従することより、検証したbyteを再現できることを優先する。02 — STAGE
payloadを一時領域へ展開し、主実行ファイルのhashを再確認してから既存配置と交換する。
途中失敗では既存client、認証状態、download済みゲームを壊さない。03 — RECEIPT
配置と補助設定が完了した後にreceiptをatomic writeする。fileの存在だけを準備完了にしない。
Windows、仮想マシン、外付けdisk、追加の展開toolを製品依存にしない。clientは起動直後にERROR_PROC_NOT_FOUND (127)で落ちていた。複数の不足symbolを一覧にしても、どれが実際にprocessを止めたかは分からない。Crashpad dumpの例外位置からdelay-IAT slotへ戻し、実行時まで関数解決を遅らせる仕組み(delay import)の対象を照合すると、load-bearingだったのはUSER32.IsWindowArrangedだった。
FAILURE
dump annotation、例外address、delay-IAT slot、PE importを一本につなぎ、実際にcrashした関数を決める。
PATCH
WineHQで追加済みのstubをforkへbackportした。独自の挙動を発明せず、元commitと返り値を保持する。
VERIFY
ImmediateCrashと新規dumpが消え、main、GPU、network、renderer processが生存した。
ここで証明したのは生存だけで、画面の中身はまだ黒い。API crashを直すとwindowは残ったが、contentは黒いままだった。hard traceが示したのはGPU能力の不足ではなく、GPU processが別process所有のWindows window handle(HWND)へVulkan surfaceを作れない境界だった。
--in-process-gpubrowser認証では、認証後に独自URL schemeでdesktop clientへ戻る。Macアプリがその戻り先を受け取る仕組みをprotocol handlerと呼ぶ。互換ランチャーは認証値を解釈せず、受け取ったURLを同じ固定client、prefix、runtimeへ渡す。
macOS既定browserへ認証を依頼する。
ユーザーが公式認証画面を操作する。
値を掲載・解析せずMac側handlerへ返す。
許可schemeだけを同じWine環境へ転送する。
公式client自身がcallbackを処理する。
Electron製clientの画面が見えても、そこから起動する32-bitゲームのfontや動画が自動で成立するとは限らない。公式client経由で購入済みゲームを起動すると、親clientとは異なるplugin、DirectShow、GStreamer経路が現れた。
| surface | 確認したこと | 別gateに残したこと |
|---|---|---|
| Electron client | login UI、library、download / install入口 | 子ゲームのrenderer、font、movie |
| Purchased game A | 公式routeの起動、本編、日本語font、起動ロゴ動画 | 一度だけ観測した未裁定hangの再発条件 |
| Purchased game B | 同じ公式routeで起動・動作 | 未取得のrenderer backend trace |
game Aの日本語fontはprefix限定設定で直し、黒い起動ロゴは子processへbundled GStreamer環境が届いていないことをtraceで確定した。親clientの成功を隣のprocessへ転用せず、子ゲーム自身のpipelineを調べた結果である。
最後に、確認できたことと確認していないことを同じ粒度で記録する。「マイゲームが見えた」から新規認証や全タイトル互換へ一般化しない。
公式channelから固定配布物を取得・照合
確認済みprefix-localへtransactional配置
確認済みprocess生存、swapchain、draw、present、visible content
確認済み非secretのprobeでMacアプリへのscheme解決
確認済み既存認証sessionで購入済みlibraryを表示
確認済み公式routeの購入済みゲーム2本を実機確認
2 / 2確認済み完全な新規sessionでbrowser callbackをend-to-end確認
未確認prefix完全不在からの初期化branch
未確認同じ製品名でも世代とframeworkが違えば診断対象は別になる。architectureとimportを先に固定する。
不足symbol、stack件数、API名のhit数で決めず、crash slotやactual callへ結ぶ。
GPU deviceを作れることと、別process所有windowへ描けることは別問題として測る。
Mac側はURLの戻り先とWine環境を所有し、公式clientの認証内容を読まない。
配信client、download、ゲーム起動、font、movie、停止制御を一つの成功へ潰さない。