Skip to content

Commit ff51537

Browse files
committed
Ensure COM threading apartment for API calls
1 parent 24f2ecd commit ff51537

File tree

1 file changed

+28
-0
lines changed

1 file changed

+28
-0
lines changed

pkg/cim/wmi.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package cim
55

66
import (
77
"fmt"
8+
"runtime"
89
"strings"
910

1011
"github.com/go-ole/go-ole"
@@ -366,3 +367,30 @@ var (
366367
func FindInstancesByObjectIDMapping(instanceToFind []*cim.WmiInstance, associatedInstances []*cim.WmiInstance, instanceMappings map[string]string) ([]*cim.WmiInstance, error) {
367368
return FindInstancesByMapping(instanceToFind, objectIDPropertyIndexer, associatedInstances, objectIDPropertyIndexer, instanceMappings)
368369
}
370+
371+
// WithCOMThread runs the given function `fn` on a locked OS thread
372+
// with COM initialized using COINIT_MULTITHREADED.
373+
//
374+
// This is necessary for using COM/OLE APIs directly (e.g., via go-ole),
375+
// because COM requires that initialization and usage occur on the same thread.
376+
//
377+
// It performs the following steps:
378+
// - Locks the current goroutine to its OS thread
379+
// - Calls ole.CoInitializeEx with COINIT_MULTITHREADED
380+
// - Executes the user-provided function
381+
// - Uninitializes COM
382+
// - Unlocks the thread
383+
//
384+
// If COM initialization fails, or if the user's function returns an error,
385+
// that error is returned by WithCOMThread.
386+
func WithCOMThread(fn func() error) error {
387+
runtime.LockOSThread()
388+
defer runtime.UnlockOSThread()
389+
390+
if err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED); err != nil {
391+
return err
392+
}
393+
defer ole.CoUninitialize()
394+
395+
return fn()
396+
}

0 commit comments

Comments
 (0)