OLE_E_NOT_INPLACEACTIVE (0x80040010) fix: object context mismatch
You get this when COM tries to in-place activate an object that's already closed or not ready. It's a timing or reference issue, not a corrupt file.
Quick answer (for advanced users)
Call IOleObject::DoVerb(OLEIVERB_INPLACEACTIVATE, ...) before any in-place editing, or fix the container's IOleInPlaceSite implementation so it correctly reports the object's activation state via GetWindowContext. The object isn't corrupt — your code's activation state machine is off.
Context: what's actually happening here
OLE_E_NOT_INPLACEACTIVE (0x80040010) shows up when a COM object's container tries to perform an in-place operation — like resizing, moving, or toolbar negotiation — but the object hasn't been properly transitioned into the in-place active state. This usually happens in Office automation, custom OLE containers (think old MFC apps), or any ActiveX document host.
The OLE spec defines a strict state machine: loaded → running → in-place active → UI active. Your code jumped the gun and tried to act on the object while it was still in 'running' or worse, 'loaded'. I've seen this most often when someone keeps a reference to an embedded Excel worksheet or Word document, closes the parent document, and then tries to edit the object again — the COM server's still there but it's been told to deactivate.
Another common trigger: calling TranslateAccelerator or OnDocWindowActivate on an object that was never in-place activated. The object doesn't know where to draw itself or handle keyboard input.
Fix steps
- Verify the object's current state
In your container code, check the object's state before calling any in-place method. CallIOleObject::GetMiscStatusand read theOLEMISCflags. If the object isn't inOLEMISC_INPLACEABLE, it can't go in-place at all — you'll need a different UI (modal editing). Most objects that throw this error are marked inplaceable but just haven't been activated yet. - Forced in-place activation before any edit
CallIOleObject::DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, lpOleClientSite, 0, hwndParent, &rcBounds)explicitly. Don't assume the object will activate itself. TheOLEIVERB_INPLACEACTIVATEverb (value 5, or -5 in some headers) forces the transition. Do this beforeTranslateAcceleratororResizeBorder. Sequence matters: always activate, then do UI work. - Check your IOleInPlaceSite implementation
The container'sIOleInPlaceSite::GetWindowContextmust return a validIOleInPlaceFrameandIOleInPlaceUIWindowpointer. If you returnNULLfor either, the object can't activate in-place and silently stays in 'running' state. Common bug: returningE_NOTIMPLor skipping the frame pointer. Implement it properly — even if you don't have toolbars, return a valid frame. - Release and re-acquire references after deactivation
If the container deactivates the object (for example, user clicks outside), the object's in-place site is invalidated. Any cached pointer to the object from before deactivation is stale. Re-query the object withQueryInterfaceforIOleObjectagain after a deactivation. Don't reuse the same pointer.
Alternative fixes if the main steps don't work
- Use OLEIVERB_OPEN instead of in-place activation
If the object consistently fails to activate in-place, switch toOLEIVERB_OPEN— this opens the object in its own window (e.g., a separate Excel window). It's less elegant but skips the entire in-place state machine. CallDoVerb(OLEIVERB_OPEN, ...)when the user double-clicks or hits Enter. - Rebuild the OLE container's site object
If you're writing the container from scratch, check that yourIOleClientSiteandIAdviseSinkimplementations aren't returningE_NOINTERFACEfor critical interfaces. A missingIOleInPlaceSiteadvise sink can cause the server to never transition to in-place active. - Disable in-place activation entirely
For older apps that don't need in-place editing (like a report generator), set the container'sOLEDRAGDROPandOLEMISCflags to suppress in-place. The object stays in 'running' state — you get less interactivity but no 0x80040010.
Prevention tip
Always treat OLE activation like a state machine, not a fire-and-forget. After any deactivation event (e.g., OnDeactivateUI), invalidate all cached object pointers. When the user re-clicks the object, force a fresh activation via DoVerb(OLEIVERB_INPLACEACTIVATE). This pattern prevents 99% of in-place state errors. Test with both Office 2016 and Office 365 — their activation timing can differ slightly.
Was this solution helpful?