0XC022000C

STATUS_FWP_WRONG_SESSION (0xC022000C) — Wrong Session Call

Windows Errors Intermediate 👁 0 views 📅 May 26, 2026

You're calling a Windows Filtering Platform API from a session that doesn't match the context. Means your app or driver is running in the wrong user session for that call.

Quick answer: This error means your code called a Windows Filtering Platform (WFP) function from a session that doesn't own the WFP session handle you passed. You need to call FwpmEngineOpen in the same session (and same process context) as the one making the subsequent WFP calls.

STATUS_FWP_WRONG_SESSION (0xC022000C) comes from fwpmk.sys or fwpuclnt.dll when you make a WFP API call with a session handle that was opened in a different user session — think Terminal Services, Fast User Switching, or a service running in Session 0 trying to use a handle opened by a logged-in user's process. The WFP kernel module tracks which session opened each handle. If you pass a handle opened in session 1 from code running in session 2, the kernel returns this exact error. I've seen this most often when a Windows service (Session 0) tries to reuse a firewall handle opened by an installer running in the user's session (Session 1). Also happens in multi-session RDP environments where one user's app tries to read another user's WFP filters.

  1. Identify the session mismatch. Determine which process is calling WFP and which process opened the session handle. In C++, check GetCurrentProcessId() and ProcessIdToSessionId() against the session ID stored when FwpmEngineOpen was called. Use Process Explorer to see each process's session column.
  2. Open a fresh WFP session in the correct context. Don't pass handles across session boundaries. If your driver or service needs WFP access, open its own session with FwpmEngineOpen specifying the appropriate session key. For a user-facing app, call FwpmEngineOpen from within the user's login session.
  3. For kernel-mode callers: If you're in a driver, use FwpsOpenToken0 to get a handle tied to the current thread's session, then call FwpmEngineOpen with that token. Don't use a handle from a different thread's context.
  4. Check your service's session affinity. Windows services run in Session 0 by default. If your service needs to manage WFP filters for a user session, run it under the user's account (e.g., as a user-mode helper process launched via CreateProcessAsUser) rather than as a system service.
  5. Verify with a reproducer: Write a small test app that opens WFP in session A, then spawns a child process in session B (via CreateProcess with STARTF_USESHOWWINDOW and a desktop name for session B). Call the WFP API from the child — you'll get 0xC022000C. Fix is to open WFP in each session independently.

Alternative fixes when the main approach fails

  • Use a named session provider: If you can't avoid cross-session work, use FwpmEngineOpen with a custom session key (a GUID you define). Both processes can call FwpmEngineOpen with the same key in their own session — but the kernel still enforces session separation. The key alone won't fix it; you must call FwpmEngineOpen in each session separately.
  • Switch to the IPortableDevice approach: Not a WFP thing, but if you're managing firewall rules, consider using the INetFwPolicy2 COM interface via CoCreateInstance with CLSID_NetFwPolicy2. This API doesn't have the same session restriction, though it's less granular than WFP.
  • For transient errors in multi-session scenarios: Retry the WFP call after a short delay (100-200ms) — the session context might have switched if you're running inside a service that's impersonating a user. Call RevertToSelf before opening WFP to ensure you use the service's own session.

Prevention tip

Design your WFP code so that each process/session pair opens its own WFP engine handle. Never store a global handle in shared memory intended for use across sessions. In services that interact with multiple user sessions, open the WFP engine inside each user impersonation block (ImpersonateLoggedOnUser + FwpmEngineOpen then RevertToSelf). This guarantees the handle is tied to the correct session. Also log the session ID when you open and close handles — makes debugging session mismatches trivial.

Was this solution helpful?