hdirect-0.21.0: comlib/ClassFactory.lhs
Haskell implementation of a COM class factory / component instance creator.
\begin{code}
{-# OPTIONS -#include "ClassFactory_stub.h" #-}
module ClassFactory
(
createClassFactory -- :: (IID a -> IO (PrimIP a)) -> IO (PrimIP ())
, iidIClassFactory
) where
import Com
import ComServ hiding ( createInstance )
import Foreign.Ptr
import ComException ( cLASS_E_NOAGGREGATION )
import IOExts
\end{code}
\begin{code}
data ClassFactory a
= ClassFactory {
new_instance :: (IID (IUnknown ()) -> IO (IUnknown ())),
lockCount :: (IORef Int)
}
type IClassFactory a = IUnknown (ClassFactory a)
type This_ClassFactory = Ptr (IClassFactory ())
iidIClassFactory :: IID (IClassFactory ())
iidIClassFactory = mkIID "{00000001-0000-0000-C000-000000000046}"
\end{code}
Class factory implementation:
\begin{code}
createInstance :: This_ClassFactory
-> Ptr (IUnknown a)
-> Ptr (IID (IUnknown ()))
-> Ptr (Ptr (IUnknown b))
-> IO HRESULT
createInstance this punkOuter riid ppv
| punkOuter /= nullPtr = return cLASS_E_NOAGGREGATION
| otherwise = do
st <- getObjState this
iid <- unmarshallIID False riid
unk <- (new_instance st) iid
writeIUnknown True ppv unk
return s_OK
lockServer :: This_ClassFactory -> Int -> IO HRESULT
lockServer this ilock = do
st <- getObjState this
let ref = lockCount st
count <- readIORef ref
if lock then
writeIORef ref (count+1)
else
writeIORef ref (count-1)
return s_OK
where
lock
| ilock == 0 = False
| otherwise = True
foreign export stdcall dynamic
export_createInstance :: (This_ClassFactory -> Ptr (IUnknown a) -> Ptr (IID (IUnknown ())) -> Ptr (Ptr (IUnknown b)) -> IO HRESULT) -> IO (Ptr ())
foreign export stdcall dynamic
export_lockServer :: (Ptr (IUnknown a) -> Int -> IO HRESULT) -> IO (Ptr ())
\end{code}
\begin{code}
createClassFactory :: (IID (IUnknown ()) -> IO (IUnknown ()))
-> IO (IClassFactory ())
createClassFactory mkInst = do
lcount <- newIORef 0
let cf_state = ClassFactory mkInst lcount
createComInstance ""
cf_state (return ())
[mkIface iidIClassFactory iClassFactory_vtbl]
iidIClassFactory
where
guidIClassFactory = iidToGUID iidIClassFactory
iClassFactory_vtbl :: VTable (IClassFactory ()) (ClassFactory ())
iClassFactory_vtbl = unsafePerformIO $ do
addrOf_cI <- export_createInstance createInstance
addrOf_lS <- export_lockServer lockServer
createComVTable [addrOf_cI, addrOf_lS]
\end{code}