//----------------------------------------------------------------------------
// ObjectComponents
// Copyright (c) 1994, 1996 by Borland International, All Rights Reserved
//
/// \file
///   Implementation of TOcApp Class
//----------------------------------------------------------------------------
#include <ocf/pch.h>
#include <ocf/autodefs.h>
#include <ocf/appdesc.h>
#include <ocf/ocreg.h>
#include <ocf/ocapp.h>
#include <ocf/ocpart.h>
# include <winver.h>
 
namespace ocf {
 
using namespace owl;
 
using namespace std;
 
DIAG_DEFINE_GROUP_INIT(OWL_INI, OcfApp, 1, 0);
DIAG_DECLARE_GROUP(OcfDll);
DIAG_DECLARE_GROUP(OcfRefCount);
 
//
/// Compatibility constructor & SetupWindow for TOcApp
//
TOcApp::TOcApp(TOcRegistrar& registrar, uint32 options, TOcApp*& retOcApp)
:
  Host(0),
  FrameHost(new TOcAppFrameHostMsg(this)), // Use default, msg based host
  OcAppPtr(&retOcApp),
  Options(options),
  DisableDlgs(false),
  Registrar(registrar),
  Registered(false)
{
  Registrar.AppCount++;
  Init();
  RegisterClasses();
 
  *OcAppPtr = this;    // Setup the client's pointer last if all else is OK
  TRACEX(OcfRefCount, 1, "TOcApp() @" << (void*)this);
 
  // !CQ Could calculate Host from OcAppPtr, assuming a TOcAppHost
  // Host = (char*)OcAppPtr - int(&(TOcAppHost*)0->OcAppPtr);
}
 
//
void TOcApp::SetupWindow(HWND frameWnd)
{
  FrameHost->SetWindow(frameWnd);  // Pass frame's hWnd over to frame host
 
  Registrar.SetApp(this);
}
 
//
/// New constructor for TOcApp using host interfaces
//
TOcApp::TOcApp(TOcRegistrar& registrar, uint32 options, TOcAppHost* host,
               TOcAppFrameHost* frameHost)
:
  Host(host),
  FrameHost(frameHost),
  OcAppPtr(0),
  Options(options),
  DisableDlgs(false),
  Registrar(registrar),
  Registered(false)
{
  PRECONDITION(&host);
  PRECONDITION(&frameHost);
 
  Registrar.AppCount++;
  Init();
  RegisterClasses();
 
  if (Host)
    Host->AttachHost(this);
 
  TRACEX(OcfRefCount, 1, "TOcApp() @" << (void*)this);
}
 
//
void TOcApp::SetupWindow(TOcAppFrameHost* frameHost)
{
  FrameHost = frameHost;
}
 
//
/// Common constructor initialization
//
void
TOcApp::Init()
{
  // Initialize BOle service ptrs that may or may not get setup later
  //
  BService = 0;
  BServiceI = 0;
 
  AddRef();  // TUnknown defaults to 0, we need 1
 
  // Create a BOle class manager for this app
  //
  BCmI = Registrar.CreateBOleClassMgr();
 
  // Create BOle service object & get its interface
  //
  BOleComponentCreate(&BService, GetOuter(), cidBOleService);
  if (BService && HRSucceeded(BService->QueryInterface(IID_IBService2,
                                                       (LPVOID *)&BServiceI))) {
    Release();
    BServiceI->Init(this);
  }
  else
    TXObjComp::Throw(TXObjComp::xBOleBindFail); // give up if no IBService2
 
  // Get the clipboard format strings
  //
  for (uint i = IDS_CFFIRST; i <= IDS_CFLAST; i++) {
    TCHAR name[128];
    if(GetGlobalModule().LoadString(i, name, 128)){
      _TCHAR* resultName = _tcschr(name, _T('\n'));
      *resultName++ = 0;
       NameList.Add(new TOcFormatName(name, resultName));
    }
  }
 
  // Get & copy the appname from the reginfo
  //
  Name = Registrar.GetAppDescriptor().GetAppName(LangSysDefault);
}
 
//
/// Clean up this object be releasing all helpers.
//
TOcApp::~TOcApp()
{
  // We're gone, make sure nobody calls us through unref'd ptr
  //
  if (OcAppPtr)     // !CQ OcAppPtr for compatibility
    *OcAppPtr = 0;
  if (Host) {
    Host->ReleaseOcObject();
    Host = 0;
  }
 
  UnregisterClasses();
 
  // RefCnt was held by controller
  //
  if (FrameHost) {
    if (FrameHost->EvOcAppShutdown() &&
        IsOptionSet(amServedApp) && !IsOptionSet(amExeModule)) {
      Registrar.Shutdown(0, Options);
    }
    FrameHost->ReleaseOcObject();
    FrameHost = 0;
  }
 
  if (BService)
    BService->Release();
  Registrar.AppCount--;
  if (BCmI)
    BCmI->Release();
}
 
//
/// Should only be called by the owner/creator of this object
//
void
TOcApp::ReleaseObject()
{
  if (Host) {
    Host->ReleaseOcObject();
    Host = 0;
  }
  if (FrameHost) {
    FrameHost->ReleaseOcObject();
    FrameHost = 0;
  }
  if (!IsOptionSet(amServedApp))
    Release();   // if our container app holds the refcnt, then release it
}
 
//
/// Callback from TUnknown's implementation of QueryInterface
//
HRESULT
TOcApp::QueryObject(const IID & iid, void * * iface)
{
  HRESULT hr;
 
  static_cast<void>
  (
  // interfaces
     SUCCEEDED(hr = IBApplication_QueryInterface(this, iid, iface))
  || SUCCEEDED(hr = IBClassMgr_QueryInterface(this, iid, iface))
 
  // helpers
  || (BService && SUCCEEDED(hr = BService->QueryInterface(iid, iface)))
  );
  return hr;
}
 
//----------------------------------------------------------------------------
 
//
/// Create a BOle helper for one of our OC objects in this app
//
HRESULT
TOcApp::BOleComponentCreate(IUnknown * * iface, IUnknown* outer, BCID idClass)
{
  return BCmI->ComponentCreate(iface, outer, idClass);
}
 
//----------------------------------------------------------------------------
// Runtime document factory registration
 
//
/// Register doc factories based on their 'progid' and their templates
//
void
TOcApp::RegisterClasses()
{
  if (Registered)
    return;
 
  // No class registration for InProc Servers
  //
  if (!(IsOptionSet(amExeModule)))
    return;
 
  // No class registration for single use apps unless embedded
  //
  if (IsOptionSet(amSingleUse) &&
     (IsOptionSet(amAutomation)|| !IsOptionSet(amEmbedding)))
    return;
 
  // Loop thru all templates, registering registerable classes
  //
  const TRegLink* link = GetRegistrar().GetAppDescriptor().GetRegLinkHead();
  for ( ; link; link = link->GetNext()) {
    TRegList&   regList = link->GetRegList();
    const _TCHAR* progid = regList[IsOptionSet(amDebug) ? "debugprogid" : "progid" ];
    if (progid) {
 
      // Don't register container classes unless embedding
      //
      if (!IsOptionSet(amEmbedding) &&
          !(const _TCHAR*)regList["insertable"])
        continue;
 
      bool multiUse = !IsOptionSet(amSingleUse);
      if (multiUse) {
        const _TCHAR* usage = regList.Lookup("usage");
        _TCHAR su[] = ocrSingleUse;
        multiUse = ToBool(!(usage && *usage == *su));
      }
      if (!RegisterClass(progid, reinterpret_cast<BCID>(link), multiUse))
        TXObjComp::Throw(TXObjComp::xDocFactoryFail);
    }
  }
  Registered = true;
}
 
//
/// Unregister doc class factories based on their 'progid' and their templates
//
void
TOcApp::UnregisterClasses()
{
  if (!Registered)
    return;
 
  // Loop thru all templates, unregistering registerable classes
  //
  const TRegLink* link = GetRegistrar().GetAppDescriptor().GetRegLinkHead();
  for ( ; link; link = link->GetNext()) {
    TRegList& regList = link->GetRegList();
    const _TCHAR* progid = regList[IsOptionSet(amDebug) ? "debugprogid" : "progid" ];
    if (progid)
      if (!UnregisterClass(progid))
        TXObjComp::Throw(TXObjComp::xDocFactoryFail);
  }
  Registered = false;
}
 
//
/// Add a user defined clipboard format name
//
void
TOcApp::AddUserFormatName(LPCTSTR name, LPCTSTR resultName, LPCTSTR id)
{
  NameList.Add(new TOcFormatName(name, resultName, id));
}
 
 
//----------------------------------------------------------------------------
// OC side exposure of selected IBService functions
 
bool
TOcApp::UnregisterClass(const owl::tstring& className)
{
  if (BServiceI)
    return HRSucceeded(BServiceI->UnregisterClass(OleStr(className.c_str())));
  return false;
}
 
//
/// Let BOle know that the main window has resized. In-place servers may need to
/// adjust their toolbars
//
void
TOcApp::EvResize()
{
  if (BServiceI)
    BServiceI->OnResize();
}
 
//
/// Let BOle know that the main window has [de]activated.
//
void
TOcApp::EvActivate(bool active)
{
  if (BServiceI)
    BServiceI->OnActivate(active);
}
 
bool
TOcApp::RegisterClass(const owl::tstring& className, BCID classId, bool multiUse)
{
  // Self-embedding works only if the app is multi-use
  //
  if (BServiceI)
    return HRSucceeded(BServiceI->RegisterClass(OleStr(className.c_str()),
                       this, classId, ToBool(multiUse), ToBool(!multiUse)));
  return false;
}
 
bool
TOcApp::CanClose()
{
  return BServiceI ? HRIsOK(BServiceI->CanClose()) : true;  // there are no servers running
}
 
uint
TOcApp::EnableEditMenu(TOcMenuEnable menuEnable, IBDataConsumer* ocView)
{
  return BServiceI ? BServiceI->EnableEditMenu(menuEnable, ocView) : 0;
}
 
bool
TOcApp::Browse(TOcInitInfo& init)
{
  return BServiceI ? HRIsOK(BServiceI->Browse(&init)) : false;
}
 
bool
TOcApp::BrowseControls(TOcInitInfo& init)
{
  return BServiceI ? HRIsOK(BServiceI->BrowseControls(&init)) : false;
}
 
bool
TOcApp::BrowseClipboard(TOcInitInfo& init)
{
  return BServiceI ? HRIsOK(BServiceI->BrowseClipboard(&init)): false;
}
 
bool
TOcApp::Paste(TOcInitInfo& init)
{
  return BServiceI ? HRIsOK(BServiceI->Paste(&init)) : false;
}
 
//
/// Copy Selected embedded object
//
bool
TOcApp::Copy(TOcPart* ocPart)
{
  IBPart* bPartI;
  if (ocPart && SUCCEEDED(ocPart->QueryInterface(IID_IBPart, (LPVOID *)&bPartI))) {
    ocPart->Release();
 
    // Copy part with delayed rendering done by Bolero
    //
    return BServiceI ? HRIsOK(BServiceI->Clip(bPartI, true, true, true)) : false;
  }
  return false;
}
 
//
/// Copy a selection in server document
//
bool
TOcApp::Copy(TOcDataProvider* ocData)
{
  PRECONDITION(ocData);
 
  if (BServiceI)
    BServiceI->Clip(0, false, false, false);
  else
    return false;
 
  return HRIsOK(BServiceI->Clip(ocData, true, true, false));
}
 
//
/// Drag a selection
//
bool
TOcApp::Drag(TOcDataProvider* ocData, TOcDropAction inAction, TOcDropAction& outAction)
{
  PRECONDITION(ocData);
 
  return BServiceI? HRSucceeded(BServiceI->Drag(ocData, inAction, &outAction)) : false;
}
 
//
/// Drag an embedded object
//
bool
TOcApp::Drag(TOcPart* ocPart, TOcDropAction inAction, TOcDropAction& outAction)
{
#if 1
  IBPart * bPartI;
  if (ocPart && SUCCEEDED(ocPart->QueryInterface(IID_IBPart, (LPVOID *)&bPartI))) {
    ocPart->Release();
    // Drag part with delayed rendering done by Bolero
    //
    return HRSucceeded(BServiceI->Drag(bPartI, inAction, &outAction));
  }
  return false;
#else
  return BServiceI? HRSucceeded(BServiceI->Drag(ocPart, inAction, &outAction)) : false;
#endif
}
 
//
/// Open the Convert dialog, and perform the conversion if OK. return true if
/// conversion was perfromed successfully.
//
bool
TOcApp::Convert(TOcPart* ocPart, bool b)
{
  PRECONDITION(ocPart);
 
  if (BServiceI == 0)
    return false;
 
  // The Convert dialog is split into two pieces: one to run the dialog box
  // and one to do the actual work. This way, the caller can record the
  // actions of the dialog box for playback later.
  //
  TOcConvertInfo ci;
  if (HRIsOK(BServiceI->ConvertUI(ocPart->GetBPartI(), b, &ci)))
    return HRSucceeded(BServiceI->ConvertGuts(ocPart->GetBPartI(), b, &ci));
 
  return false;
}
 
//----------------------------------------------------------------------------
// IBApplication implementation
 
//
/// Return the application's name
//
LPCOLESTR _IFUNC
TOcApp::GetAppName()
{
  return Name;
}
 
TOcHelp _IFUNC
TOcApp::HelpMode(TOcHelp /*newMode*/)
{
  // No built in help support
  //
  return hlpExit;
}
 
//
/// Insert the container's menus into a provided menubar
//
HRESULT _IFUNC
TOcApp::InsertContainerMenus(HMENU hMenu, TOcMenuWidths * omw)
{
  PRECONDITION(omw);
  if (!hMenu)
    return HR_NOERROR;
 
  TOcMenuDescr md;
  md.HMenu = hMenu;
 
  int i;
  for (i = 0; i < 6; i++) {
    md.Width[i]    = 0;  // make sure the server's are zeroed
    omw->Width[i] = 0;  // make sure the server's are zeroed
    i++;
    md.Width[i] = (int)omw->Width[i];
  }
 
  if (!FrameHost || !FrameHost->EvOcAppInsMenus(md))
    return HR_FAIL;
 
  for (i = 0; i < 6; i++)
    omw->Width[i] = md.Width[i];
 
  return HR_NOERROR;
}
 
//
/// Now set the provided menubar into the container's main frame window
//
HRESULT _IFUNC
TOcApp::SetFrameMenu(HMENU hMenu)
{
  TOcMenuDescr md;
  md.HMenu = hMenu;
  return HRFailIfZero(FrameHost && FrameHost->EvOcAppMenus(md));
}
 
//
//
//
HRESULT _IFUNC
TOcApp::Accelerator(MSG* msg)
{
  PRECONDITION(msg);
 
  return HRFailIfZero(FrameHost && FrameHost->EvOcAppProcessMsg(msg));
}
 
//
/// Let BOle know if we (container app) have an accelerator table
//
HRESULT _IFUNC
TOcApp::GetAccelerators(HACCEL * phAccel, int * pcAccel)
{
  TOcGetAccel acc;
  if (FrameHost) {
    if (FrameHost->EvOcAppGetAccel(&acc)) {
      *phAccel = acc.Accel;
      *pcAccel = acc.Count;
      return HR_NOERROR;
    }
  }
  return HR_FAIL;  // would retrieve or generate an accelerator table here
}
 
//
/// Let BOle know if this app can/will accept links
//
HRESULT _IFUNC
TOcApp::CanLink()
{
  return HR_OK;  // return HR_FAIL to disallow Linking
}
 
//
/// Let BOle know if this app can/will accept embeddings
//
HRESULT _IFUNC
TOcApp::CanEmbed()
{
  return HR_OK;  // return HR_FAIL to disallow Embedding
}
 
//
/// Get and return the app frame's HWND
//
HWND _IFUNC
TOcApp::GetWindow()
{
  return FrameHost ? FrameHost->EvOcGetWindow() : 0;
}
 
//
// Get client rectangle of app's main frame window
//
HRESULT _IFUNC
TOcApp::GetWindowRect(TRect* r)
{
  PRECONDITION(r);
 
  return HRFailIfZero(FrameHost && FrameHost->EvOcAppFrameRect(r));
}
 
//
/// Return the app's title, same as GetAppName()
//
LPCOLESTR _IFUNC
TOcApp::GetWindowTitle()
{
  return Name;
}
 
//
/// The server is asking for space along the app borders to put toolbars, etc.
/// This call is used to determine whether the container is willing and able to
/// provide a given combination.
//
HRESULT _IFUNC
TOcApp::RequestBorderSpace(const TRect* space)
{
  TRect* nc_space = CONST_CAST(TRect*, space); /// Ack!
  return HRFailIfZero(FrameHost && FrameHost->EvOcAppBorderSpaceReq(nc_space));
}
 
//
/// Now, actually provide the space along the app frame borders for inplace
/// server adornments
//
HRESULT _IFUNC
TOcApp::SetBorderSpace(const TRect* space)
{
  TRect * nc_space = CONST_CAST(TRect*, space); /// Ack!
  return HRFailIfZero(FrameHost && FrameHost->EvOcAppBorderSpaceSet(nc_space));
}
 
//
/// Append supplied Ole title to frame's title, saving old title
//
void _IFUNC
TOcApp::AppendWindowTitle(LPCOLESTR /*title*/)
{
  ///
}
 
//
/// Pass status bar text to container app to have app display it
//
HRESULT _IFUNC
TOcApp::SetStatusText(LPCOLESTR text)
{
  // Convert OLE str into ANSI
  //
  if (FrameHost) {
    FrameHost->EvOcAppStatusText(OleStr(text));
    return HR_OK;
  }
  return HR_FAIL;
//  return HRFailIfZero(FrameHost && FrameHost->EvOcAppStatusText(OleStr(text)));
}
 
//
/// Respond to let BOle know if our app is MDI or not
//
HRESULT _IFUNC
TOcApp::IsMDI()
{
  // Since this flag is used only to do toolbar negotiation,
  // we're always MDI as far as BOle is concerned.
  //
  return HR_NOERROR;
}
 
//
/// The server is entering or leaving a modal state. Keep track so that we don't
/// interfere when it is modal.
//
HRESULT _IFUNC
TOcApp::OnModalDialog(BOOL svrModal)
{
  DisableDlgs = (bool)svrModal;
  return HR_NOERROR;
}
 
//
/// The in-place server is done. Tell the container to restore its normal UI.
/// We can handle the window text here, let the app do the rest.
//
void _IFUNC
TOcApp::RestoreUI()
{
  SetStatusText(0);
  if (FrameHost)
    FrameHost->EvOcAppRestoreUI();
}
 
//
//
//
void _IFUNC
TOcApp::DialogHelpNotify(TOcDialogHelp help)
{
  if (FrameHost)
    FrameHost->EvOcAppDialogHelp(help);
}
 
//
/// Called by BOle when last embedding is closed
/// If that's the only reason the app is up we need to shut ourselves down
//
void _IFUNC
TOcApp::ShutdownMaybe()
{
  TRACEX(OcfApp, 1,
         "ShutdownMaybe() on " << (void*)this <<
         " Embedding:" << (int)ToBool(IsOptionSet(amEmbedding)) <<
         " Win:" << hex << static_cast<void*>(GetWindow()));
 
  // Check first to see if TOcApp should initiate a shutdown
  //
  if (!FrameHost || FrameHost->EvOcAppShutdown() || !GetWindow()) {
    // The server initiated the shutdown
    //
    if (!IsOptionSet(amExeMode)) {  // DLL server
      AddRef();    // Prevent destroying ourselves yet
      Registrar.Shutdown((IUnknown*)(void*)this, Options);
      Release();   // This should do us in now
    }
  }
}
 
//-----------------------------------------------------------------------------
// TOcClassMgr, IBClassMgr implementation for TOcRegistrar
//
 
class _ICLASS TOcClassMgr : private TUnknown, public IBClassMgr {
  public:
    TOcClassMgr(TComponentFactory cc, uint32 options);
    ~TOcClassMgr();
    ulong _IFUNC   AddRef() ;
    ulong _IFUNC   Release();
 
    void            SetApp(TOcApp* app) {OcApp = app;}
 
  private:
    HRESULT _IFUNC QueryInterface(const GUID & iid, void ** iface)
                     {return GetOuter()->QueryInterface(iid, iface);}
    HRESULT _IFUNC ComponentCreate(IUnknown * * iface,
                                   IUnknown * outer, BCID classId);
    HRESULT _IFUNC ComponentInfoGet(IUnknown * * info,
                                    IUnknown * outer, BCID classId);
    // TUnknown virtual overrides
    //
    HRESULT      QueryObject(const IID & iid, void * * iface);
 
    TComponentFactory   OcCallback;    // Callback for creating component
    uint32              Options;       // Options flags from TOcRegistrar
    TOcApp*    OcApp;
    friend class TOcApp;  // could delegate the interface instead...
};
 
TOcClassMgr::TOcClassMgr(TComponentFactory cc, uint32 options)
:
  OcCallback(cc),
  Options(options),
  OcApp (0)
{
}
 
TOcClassMgr::~TOcClassMgr()
{
}
 
ulong _IFUNC
TOcClassMgr::AddRef()
{
  return GetOuter()->AddRef();
}
 
ulong _IFUNC
TOcClassMgr::Release()
{
  return GetOuter()->Release();
}
 
//
// IBClassMgr implementation for TOcRegistrar
//
HRESULT _IFUNC
TOcClassMgr::ComponentCreate(IUnknown * * retIface, IUnknown * outer, BCID idClass)
{
  PRECONDITION(idClass && retIface);
 
  *retIface = 0;
  if (!OcCallback)
    return HR_FAIL;
 
  try {
 
    // Test for special condition to force run as an EXE
    //
    void * v;
    if (outer && !(Options & amExeModule) && outer->QueryInterface(IID_NULL, &v) == HR_NOERROR)
      *retIface = OcCallback(0, Options | amExeMode | amRun, idClass);
    else
      *retIface = OcCallback(outer, Options | amEmbedding, idClass);
    return *retIface ? HR_OK : HR_FAIL;
  }
  catch (...) {  // we can't throw any exception through OLE
    // if an exception occur shutdown the application if it needs to be so
    if (OcApp)
      OcApp->ShutdownMaybe ();
 
    return HR_OUTOFMEMORY;  // probably a resource problem, better error code?
  }
}
 
HRESULT _IFUNC
TOcClassMgr::ComponentInfoGet(IUnknown * * info, IUnknown * /*outer*/,
                              BCID /*idClass*/)
{
  *info = 0;
  return HR_FAIL;
}
 
HRESULT
TOcClassMgr::QueryObject(const IID & iid, void * * iface)
{
  HRESULT hr;
 
  // interfaces
  HRSucceeded(hr = IBClassMgr_QueryInterface(this, iid, iface))
  ;
  return hr;
}
 
//----------------------------------------------------------------------------
// IBClassMgr implementation for TOcApp
//
 
HRESULT _IFUNC
TOcApp::ComponentCreate(IUnknown * * ret, IUnknown * outer, BCID classId)
{
  return Registrar.OcClassMgr->ComponentCreate(ret, outer, classId);
}
 
HRESULT _IFUNC
TOcApp::ComponentInfoGet(IUnknown * * info, IUnknown * outer, BCID classId)
{
  return Registrar.OcClassMgr->ComponentInfoGet(info, outer, classId);
}
 
//-----------------------------------------------------------------------------
// TOcRegistrar
//
/// The 'preselectedOptions' parameter enables to preserve old (pre 6.40)
/// behaviour (see Bug #376):
/// Set to amQuietReg, no exception is thrown on registration failures 
/// which nowadays occur frequently due to restricted user rights during
/// registration updates.
/// This option should only be set when cmdLine is empty, otherwise wanted 
/// exceptions on registration failures will be suppressed too.
/// The amNoRegValidate bit may be set to suppress the automatic registration
/// update at all.
//
TOcRegistrar::TOcRegistrar(TRegList& regInfo, TComponentFactory callback,
                           owl::uint32 preselectedOptions, 
                           owl::tstring& cmdLine, TRegLink* linkHead,
                           TModule* module)
:
  TRegistrar(*new TAppDescriptor(regInfo, callback, cmdLine, module, linkHead, preselectedOptions)),
  BOleInstance(0),
  BCmI(0),
  OcClassMgr(0),
  AppCount(0)
{
  OcClassMgr = new TOcClassMgr(callback, GetOptions());
  OcClassMgr->AddRef();
}
 
TOcRegistrar::~TOcRegistrar()
{
  if (BCmI)
    BCmI->Release();
  if (OcClassMgr)
    OcClassMgr->Release();
  if (BOleInstance > HINSTANCE(32))
    ::FreeLibrary(BOleInstance);
}
 
//
// Create and return a BOle class manager helper interface with 1 ref on it
//
 
typedef HRESULT (PASCAL *TCreateClassMgr)(IUnknown**, IUnknown*, IMalloc*);
 
IBClassMgr*
TOcRegistrar::CreateBOleClassMgr()
{
  if (!BOleInstance)
    LoadBOle();
  TCreateClassMgr createClassMgr = (TCreateClassMgr)::GetProcAddress(BOleInstance, BOLEBIND);
  if (createClassMgr) {
 
    // Call thru the exported function to get a BOle class manager
    // Don't aggregate it to anything
    //
    IUnknown*   bcm;
    createClassMgr(&bcm, 0, 0);
    if (bcm) {
      IBClassMgr* bcmi = NULL;
      bcm->QueryInterface(IID_IBClassMgr, (LPVOID  *)&bcmi);
      bcm->Release();
      if (bcmi)
        return bcmi;
    }
  }
  TXObjComp::Throw(TXObjComp::xBOleBindFail);
  return 0; // never reached
}
 
//
/// Override TRegistrar's GetFactory to provide additional factory support
/// using BOle factories
//
void*
TOcRegistrar::GetFactory(const GUID& clsid, const GUID& iid)
{
  void* factory = TRegistrar::GetFactory(clsid, iid);
  if (factory)
    return factory;
 
  if (!BCmI)
    BCmI = CreateBOleClassMgr();
 
  IUnknown* objFactory = 0;
  IBClass* classMgr    = 0;
 
  TRegLink* link = GetAppDescriptor().GetRegLink(clsid);
  if (!link)
    return 0;
 
  TRegList&   regList = link->GetRegList();
  LPCTSTR progid = regList[IsOptionSet(amDebug) ? "debugprogid" : "progid" ];
 
  // Create BoleFactory helper object & init it, giving it our OcClassMgr
  // object to work with
  //
  if (!(HRSucceeded(BCmI->ComponentCreate(&objFactory, 0, cidBOleFactory)) &&
      HRSucceeded(objFactory->QueryInterface(IID_IBClass, (LPVOID *)&classMgr)) &&
      HRSucceeded(classMgr->Init(false, OleStr(progid), OcClassMgr, reinterpret_cast<BCID>(link))) &&
      HRSucceeded(classMgr->QueryInterface(iid, &factory)))) {
    if (objFactory)
      objFactory->Release();
    if (classMgr)
      classMgr->Release();
 
    return 0;
  }
 
  return factory;
}
 
bool
TOcRegistrar::CanUnload()
{
  TRACEX(OcfDll, 1, "CanUnload() AppCount:" << AppCount);
  return TRegistrar::CanUnload() && AppCount == 0;
}
 
void
TOcRegistrar::SetApp(TOcApp* app)
{
  OcClassMgr->SetApp(app);
}
 
static bool
sGetFileVersionInfo(LPCTSTR fileName, VS_FIXEDFILEINFO& vInfo)
{
  OLECHAR* viBuff;      // version buffer
  uint32   infoSize;    // Size of version info resource in file
 
  // Find out how big the file version info buffer is supposed to be and
  // create a buffer of that size
  //
  uint32 infoHandle;
  infoSize = ::GetFileVersionInfoSize(OleStr(fileName), &infoHandle);
  if (infoSize == 0)
    return false;
 
  viBuff = new OLECHAR[(int)infoSize];
 
  // Copy the file version info buffer from the file into viBuff
  //
  if (::GetFileVersionInfo(OleStr(fileName), 0, infoSize, viBuff)) {
 
    // Perform some magic on the phantom buffer to get an actual structure with
    // the version information
    //
    uint vInfoLen;
    VS_FIXEDFILEINFO * vInfoPtr;
    if (::VerQueryValue(viBuff, _T("\\"), (LPVOID *)&vInfoPtr, &vInfoLen)) {
      vInfo = *vInfoPtr;
      delete[] viBuff;
      return true;
    }
  }
  delete[] viBuff;
  return false;
}
 
//
/// Dynamically load the OcOle Dll, get the one entry point that we need &
/// make the class manager object that we use
//
void
TOcRegistrar::LoadBOle()
{
  // Select the most appropiate BOCOLE
  // For UNICODE priority is: Unicode-Debug (in debug build), Unicode, Ansi
  // For ANSI priority is: Ansi-Debug (in debug build), Ansi
    _TCHAR name[32];
    WIN32_FIND_DATA wfd;
    HANDLE handle = INVALID_HANDLE_VALUE;
#ifdef UNICODE
 
#ifdef _DEBUG
    handle = ::FindFirstFile(BOLEDLLDW, &wfd);
    if (handle != INVALID_HANDLE_VALUE) {
        ::FindClose(handle);
        if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
            handle = INVALID_HANDLE_VALUE;
        }
        else
            _tcscpy(name, BOLEDLLDW);
    }
#endif
    if (handle == INVALID_HANDLE_VALUE) {
        handle = ::FindFirstFile(BOLEDLLW, &wfd);
        if (handle != INVALID_HANDLE_VALUE) {
            ::FindClose(handle);
            if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                handle = INVALID_HANDLE_VALUE;
            }
            else
                _tcscpy(name, BOLEDLLW);
        }
    }
#else   //ANSI
 
#ifdef _DEBUG
    if (handle == INVALID_HANDLE_VALUE) {
        handle = ::FindFirstFile(BOLEDLLD, &wfd);
        if (handle != INVALID_HANDLE_VALUE) {
            ::FindClose(handle);
            if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                handle = INVALID_HANDLE_VALUE;
            }
            else
                _tcscpy(name, BOLEDLLD);
        }
    }
#endif
 
#endif
    //If no UNICODE 'bocole'.dll then go for the classic ANSI version
    if (handle == INVALID_HANDLE_VALUE) {
        _tcscpy(name, BOLEDLL);
        handle = ::FindFirstFile(BOLEDLL, &wfd);
        if (handle != INVALID_HANDLE_VALUE) {
            ::FindClose(handle);
            if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                handle = INVALID_HANDLE_VALUE;
            }
        }
    }
 
    if (handle != INVALID_HANDLE_VALUE) {
        VS_FIXEDFILEINFO vInfo;
        if (!sGetFileVersionInfo(name, vInfo) ||
            vInfo.dwFileVersionMS < BOLE_FILEVER_MS ||
            ( vInfo.dwFileVersionMS == BOLE_FILEVER_MS
              && vInfo.dwFileVersionLS < BOLE_FILEVER_LS )
           )
            TXObjComp::Throw(TXObjComp::xBOleVersFail);
 
        BOleInstance = ::LoadLibrary(wfd.cFileName);
    }
 
  // If we failed to load the DLL, throw a general cannot-load exception.
  // Otherwise get the class manager interface
  //
  if (BOleInstance <= HINSTANCE(32))
    TXObjComp::Throw(TXObjComp::xBOleLoadFail);
}
 
//-----------------------------------------------------------------------------
// TOcFormatName
//
 
TOcFormatName::TOcFormatName()
{
}
 
TOcFormatName::TOcFormatName(LPCTSTR name, LPCTSTR resultName, LPCTSTR id)
:
  Name(name),
  ResultName(resultName),
  Id( id ? id : _T(""))
{
}
 
//----------------------------------------------------------------------------
// TOcNameList
//
 
TOcNameList::TOcNameList()
{
}
 
TOcNameList::~TOcNameList()
{
  Clear();
}
 
//
/// Find the format name with the corresponding id
//
TOcFormatName*
TOcNameList::operator [](LPTSTR id)
{
  for (uint i = 0; i < Count(); i++) {
    TOcFormatName* formatName = (*this)[i];
    if (_tcscmp(formatName->GetId(), id) == 0)
      return formatName;
  }
 
  return 0;
}
 
//----------------------------------------------------------------------------
// TOcInitInfo
//
 
TOcInitInfo::TOcInitInfo(IBContainer * container)
:
  How(ihEmbed),
  Where(iwNew),
  Container(container),
  HIcon(0),
  Storage(0)
{
}
 
TOcInitInfo::TOcInitInfo(TOcInitHow how, TOcInitWhere where, IBContainer * container)
:
  How(how),
  Where(where),
  Container(container),
  HIcon(0),
  Storage(0)
{
}
 
//----------------------------------------------------------------------------
// Default FrameHost class implementation for compatibility. Forwards events
// to FrameWindow using windows messages
//
 
//
bool
TOcAppFrameHostMsg::EvOcAppInsMenus(TOcMenuDescr & sharedMenu)
{
  return (bool)ForwardEvent(OC_APPINSMENUS, &sharedMenu);
}
 
bool
TOcAppFrameHostMsg::EvOcAppMenus(TOcMenuDescr & md)
{
  return (bool)ForwardEvent(OC_APPMENUS, &md);
}
 
bool
TOcAppFrameHostMsg::EvOcAppProcessMsg(MSG * msg)
{
  return (bool)ForwardEvent(OC_APPPROCESSMSG, msg);
}
 
bool
TOcAppFrameHostMsg::EvOcAppFrameRect(TRect * rect)
{
  return (bool)ForwardEvent(OC_APPFRAMERECT, rect);
}
 
bool
TOcAppFrameHostMsg::EvOcAppBorderSpaceReq(TRect * space)
{
  return (bool)ForwardEvent(OC_APPBORDERSPACEREQ, space);
}
 
bool
TOcAppFrameHostMsg::EvOcAppBorderSpaceSet(TRect * space)
{
  return (bool)ForwardEvent(OC_APPBORDERSPACESET, space);
}
 
void
TOcAppFrameHostMsg::EvOcAppStatusText(const char * text)
{
  ForwardEvent(OC_APPSTATUSTEXT, text);
}
 
void
TOcAppFrameHostMsg::EvOcAppRestoreUI()
{
  ForwardEvent(OC_APPRESTOREUI);
}
 
void
TOcAppFrameHostMsg::EvOcAppDialogHelp(TOcDialogHelp & help)
{
  ForwardEvent(OC_APPDIALOGHELP, help);
}
 
bool
TOcAppFrameHostMsg::EvOcAppShutdown()
{
  return (bool)ForwardEvent(OC_APPSHUTDOWN);
}
 
bool
TOcAppFrameHostMsg::EvOcAppGetAccel(TOcGetAccel * acc)
{
  return ForwardEvent(OC_APPGETACCEL, acc);
}
 
TResult
TOcAppFrameHostMsg::ForwardEvent(int eventId, const void* param)
{
  HWND hWnd = EvOcGetWindow();
  if (::IsWindow(hWnd))
    return ::SendMessage(hWnd, WM_OCEVENT, eventId, (LPARAM)param);
 
  return 0;
}
 
TResult
TOcAppFrameHostMsg::ForwardEvent(int eventId, TParam2 param)
{
  HWND hWnd = EvOcGetWindow();
  if (::IsWindow(hWnd))
    return ::SendMessage(hWnd, WM_OCEVENT, eventId, param);
 
  return 0;
}
 
} // OCF namespace
 
//==============================================================================
 

V205 Explicit conversion of pointer type to 32-bit integer type: reinterpret_cast< BCID > (link)

V205 Explicit conversion of pointer type to 32-bit integer type: reinterpret_cast< BCID > (link)

V530 The return value of function 'HRSucceeded' is required to be utilized.

V1004 The 'ocPart' pointer was used unsafely after it was verified against nullptr. Check lines: 450, 460.

V1004 The 'retIface' pointer was used unsafely after it was verified against nullptr. Check lines: 780, 782.

V1004 The 'omw' pointer was used unsafely after it was verified against nullptr. Check lines: 492, 502.

V669 The 'help' argument is a non-constant reference. The analyzer is unable to determine the position at which this argument is being modified. It is possible that the function contains an error.

V769 The 'resultName' pointer in the 'resultName ++' expression could be nullptr. In such case, resulting value will be senseless and it should not be used.

V832 It's better to use '= default;' syntax instead of empty constructor body.

V832 It's better to use '= default;' syntax instead of empty constructor body.