struct CClassFactory{
  dword vtbl;//IClassFactory

  CClassFactory(dword clsid);
  ~CClassFactory();

  dword QueryInterface(dword riid, ppReturn);
  dword AddRef();
  dword Release();
  dword CreateInstance(dword pUnknown, riid, ppObject);
  dword LockServer(dword x);

  dword m_ObjRefCount;
  GUID  m_clsidObject;
};

CClassFactory::~CClassFactory(){
  g_DllRefCount--;
}

dword CClassFactory::AddRef(){
  $push ESI
  m_ObjRefCount++;
  EAX=m_ObjRefCount;
  $pop ESI
}

dword CClassFactory::QueryInterface(dword riid, ppReturn){
  dword hResult=E_NOINTERFACE;
  $pushad
  DSDWORD[ppReturn] = NULL;
  IF(IsEqualIID(riid, #IID_IUnknown))
  ||(IsEqualIID(riid, #IID_IClassFactory)){
    DSDWORD[ppReturn] = this;
    AddRef();//COMETHOD(this,#IUnknownVtbl.AddRef);//(*(LPUNKNOWN*)ppReturn)->AddRef();
    hResult=S_OK;
  }
  $popad
  return hResult;
}

dword CClassFactory::Release(){
  $push ESI
  m_ObjRefCount--;
  EAX=m_ObjRefCount;
  IF(!EAX)delete this CClassFactory;
  $pop ESI
}

dword CClassFactory::CreateInstance(dword pUnknown, riid, ppObject){
  dword pButton;
  dword hResult=E_FAIL;

  $pushad
  DSDWORD[ppObject] = NULL;
  IF(pUnknown != NULL) {
    hResult=CLASS_E_NOAGGREGATION;
  }ELSE{
    IF(IsEqualCLSID(#m_clsidObject, #pluginCLSID)){
      pButton = new CMyBtn();
      IF(! pButton ){
        hResult=E_OUTOFMEMORY;
      }ELSE{
        hResult = COMETHOD(pButton, #IUnknownVtbl.QueryInterface, riid, ppObject);
        COMETHOD(pButton,#IUnknownVtbl.Release);
      }
    }
  }
  $popad
  return hResult;
}

dword CClassFactory::LockServer(dword x){
  return E_NOTIMPL;
}

dword CClassFactoryVtbl=
{ #EAX.CClassFactory.QueryInterface
 ,#EAX.CClassFactory.AddRef
 ,#EAX.CClassFactory.Release
  //IClassFactory methods
 ,#EAX.CClassFactory.CreateInstance
 ,#EAX.CClassFactory.LockServer
};

CClassFactory::CClassFactory(dword clsid){
  $pushad
  vtbl=#CClassFactoryVtbl;
  CopyMemory(#m_clsidObject, clsid, sizeof(CClassFactory.m_clsidObject));
  m_ObjRefCount=1;
  g_DllRefCount++;
  $popad
  return this;
}
