home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 May / Pcwk5b98.iso / Borland / Cplus45 / BC45 / OCFSRC.PAK / OCAPP.CPP < prev    next >
C/C++ Source or Header  |  1995-08-29  |  26KB  |  1,042 lines

  1. //
  2. //----------------------------------------------------------------------------
  3. // ObjectComponents
  4. // (C) Copyright 1994 by Borland International, All Rights Reserved
  5. //
  6. //   Implementation of TOcApp Class
  7. //----------------------------------------------------------------------------
  8. #include <ocf/ocfpch.h>
  9. #include <ocf/autodefs.h>
  10. #include <ocf/appdesc.h>
  11. #include <ocf/ocreg.h>
  12. #include <ocf/ocapp.h>
  13. #include <ocf/ocpart.h>
  14. #if defined(BI_PLAT_WIN32)
  15. # include <winver.h>
  16. #elif defined(BI_PLAT_WIN16)
  17. # include <ver.h>
  18. #endif
  19.  
  20. DIAG_DEFINE_GROUP(OcApp, true, 1);
  21. DIAG_DECLARE_GROUP(OcDll);
  22. DIAG_DECLARE_GROUP(OcRefCount);
  23.  
  24. //
  25. // Constructor for TOcApp
  26. //
  27. TOcApp::TOcApp(TOcRegistrar& registrar, uint32 options, TOcApp*& retOcApp)
  28. :
  29.   OcAppPtr(retOcApp),
  30.   Options(options),
  31.   FrameWnd(0),
  32.   DisableDlgs(false),
  33. #if defined(BI_DATA_NEAR)
  34.   Name(*new TString),
  35.   NameList(*new TOcNameList),
  36. #endif
  37.   Registrar(registrar),
  38.   Registered(false)
  39. {
  40.   Registrar.AppCount++;
  41.   Init();
  42.   RegisterClasses();
  43.   retOcApp = this;    // setup the client's pointer last if all else is OK
  44.   TRACEX(OcRefCount, 1, "TOcApp() @" << (void*)this);
  45. }
  46.  
  47. //
  48. // Common constructor initialization
  49. //
  50. void
  51. TOcApp::Init()
  52. {
  53.   // Initialize BOle service ptrs that may or may not get setup later
  54.   //
  55.   BService = 0;
  56.   BServiceI = 0;
  57.  
  58.   AddRef();  // TUnknown defaults to 0, we need 1
  59.  
  60.   // Create a BOle class manager for this app
  61.   //
  62.   BCmI = Registrar.CreateBOleClassMgr();
  63.  
  64.   // Create BOle service object & get its interface
  65.   //
  66.   BOleComponentCreate(&BService, GetOuter(), cidBOleService);
  67.   if (BService && HRSucceeded(BService->QueryInterface(IID_IBService,
  68.                                                        &(LPVOID)BServiceI))) {
  69.     Release();
  70.     BServiceI->Init(this);
  71.   }
  72.   else
  73.     TXObjComp::Throw(TXObjComp::xBOleBindFail); // give up if no IBService
  74.  
  75. #if defined(BI_PLAT_WIN16)
  76.   // Make this task's message queue larger for Ole.
  77.   // This is necessary for all Win16 apps requiring LRPC calls.
  78.   //
  79.   int queueSize = 96;
  80.   while (!::SetMessageQueue(queueSize) && queueSize > 0)
  81.     queueSize -= 8;
  82. #endif
  83.  
  84.   // Get the clipboard format strings
  85.   //
  86.   for (uint i = IDS_CFFIRST; i <= IDS_CFLAST; i++) {
  87.     char name[128];
  88.     if (::FindResource(_hInstance, MAKEINTRESOURCE(i/16+1), RT_STRING)) {
  89.       if (::LoadString(_hInstance, i, name, 128)) {
  90.         char far* resultName = strchr(name, '\n');
  91.         *resultName++ = 0;
  92.         NameList.Add(new TOcFormatName(name, resultName));
  93.       }
  94.     }
  95.   }
  96.  
  97.   // Get & copy the appname from the reginfo
  98.   //
  99.   Name = Registrar.GetAppDescriptor().GetAppName(LangSysDefault);
  100. }
  101.  
  102. //
  103. // Clean up this object be releasing all helpers.
  104. //
  105. TOcApp::~TOcApp()
  106. {
  107.   OcAppPtr = 0;  // we're gone, make sure nobody calls us through unref'd ptr
  108.   UnregisterClasses();
  109.  
  110.   // refcnt was held by controller
  111.   //
  112.   if (ForwardEvent(OC_APPSHUTDOWN) && IsOptionSet(amServedApp) &&
  113.       !IsOptionSet(amExeModule)) {
  114.     Registrar.Shutdown(0, Options);
  115.   }
  116.  
  117.   if (BService)
  118.     BService->Release();
  119. #if defined(BI_DATA_NEAR)
  120.   delete &Name;
  121.   delete &NameList;
  122. #endif
  123.   Registrar.AppCount--;
  124.   if (BCmI)
  125.     BCmI->Release();
  126. }
  127.  
  128. //
  129. // Should only be called by the owner/creator of this object
  130. //
  131. void
  132. TOcApp::ReleaseObject()
  133. {
  134.   FrameWnd = 0;
  135.   if (!IsOptionSet(amServedApp))
  136.     Release();   // if our container app holds the refcnt, then release it
  137. }
  138.  
  139. //
  140. // Callback from TUnknown's implementation of QueryInterface
  141. //
  142. HRESULT
  143. TOcApp::QueryObject(const IID far& iid, void far* far* iface)
  144. {
  145.   HRESULT hr;
  146.  
  147.   // interfaces
  148.      SUCCEEDED(hr = IBApplication_QueryInterface(this, iid, iface))
  149.   || SUCCEEDED(hr = IBClassMgr_QueryInterface(this, iid, iface))
  150.  
  151.   // helpers
  152.   || (BService && SUCCEEDED(hr = BService->QueryInterface(iid, iface)))
  153.   ;
  154.   return hr;
  155. }
  156.  
  157. //----------------------------------------------------------------------------
  158.  
  159. //
  160. // Create a BOle helper for one of our OC objects in this app
  161. //
  162. HRESULT
  163. TOcApp::BOleComponentCreate(IUnknown far* far* iface, IUnknown* outer, BCID idClass)
  164. {
  165.   return BCmI->ComponentCreate(iface, outer, idClass);
  166. }
  167.  
  168. //----------------------------------------------------------------------------
  169. // Runtime document factory registration
  170.  
  171. //
  172. // Register doc factories based on their 'progid' and their templates
  173. //
  174. void
  175. TOcApp::RegisterClasses()
  176. {
  177.   if (Registered)
  178.     return;
  179.   if (!(IsOptionSet(amExeModule)))
  180.     return;     // no class registration for inproc servers
  181.   if (IsOptionSet(amSingleUse) &&
  182.      (IsOptionSet(amAutomation)||
  183.      !IsOptionSet(amEmbedding)))
  184.     return;     // no class registration for single use apps unless embedded
  185.  
  186.   // Loop thru all templates, registering registerable classes
  187.   //
  188.   const TRegLink* link = GetRegistrar().GetAppDescriptor().GetRegLinkHead();
  189.   for ( ; link; link = link->GetNext()) {
  190.     TRegList&   regList = link->GetRegList();
  191.     const char* progid = regList[IsOptionSet(amDebug) ? "debugprogid" : "progid" ];
  192.     if (progid) {
  193.       if (!IsOptionSet(amEmbedding) &&
  194.           !(const char*)regList["insertable"])
  195.         continue;   // don't register container classes unless embedding
  196.  
  197.       bool multiUse = !IsOptionSet(amSingleUse);
  198.       if (multiUse) {
  199.         const char* usage = regList.Lookup("usage");
  200.         char su[] = ocrSingleUse;
  201.         multiUse = ToBool(!(usage && *usage == *su));
  202.       }
  203.       if (!RegisterClass(progid, reinterpret_cast<BCID>(link), multiUse))
  204.         TXObjComp::Throw(TXObjComp::xDocFactoryFail);
  205.     }
  206.   }
  207.   Registered = true;
  208. }
  209.  
  210. //
  211. // Unregister doc class factories based on their 'progid' and their templates
  212. //
  213. void
  214. TOcApp::UnregisterClasses()
  215. {
  216.   if (!Registered)
  217.     return;
  218.  
  219.   // Loop thru all templates, unregistering registerable classes
  220.   //
  221.   const TRegLink* link = GetRegistrar().GetAppDescriptor().GetRegLinkHead();
  222.   for ( ; link; link = link->GetNext()) {
  223.     TRegList& regList = link->GetRegList();
  224.     const char* progid = regList[IsOptionSet(amDebug) ? "debugprogid" : "progid" ];
  225.     if (progid)
  226.       if (!UnregisterClass(progid))
  227.         TXObjComp::Throw(TXObjComp::xDocFactoryFail);
  228.   }
  229.   Registered = false;
  230. }
  231.  
  232. //
  233. // Add a user defined clipboard format name
  234. //
  235. void
  236. TOcApp::AddUserFormatName(const char far* name, const char far* resultName, const char far* id)
  237. {
  238.   NameList.Add(new TOcFormatName(name, resultName, id));
  239. }
  240.  
  241.  
  242. //----------------------------------------------------------------------------
  243. // OC side exposure of selected IBService functions
  244.  
  245. bool
  246. TOcApp::UnregisterClass(const string& className)
  247. {
  248.   if (BServiceI)
  249.     return HRSucceeded(BServiceI->UnregisterClass(OleStr(className.c_str())));
  250.   return false;
  251. }
  252.  
  253. //
  254. // Let BOle know that the main window has resized. In-place servers may need to
  255. // adjust their toolbars
  256. //
  257. void
  258. TOcApp::EvResize()
  259. {
  260.   if (BServiceI)
  261.     BServiceI->OnResize();
  262. }
  263.  
  264. //
  265. // Let BOle know that the main window has [de]activated.
  266. //
  267. void
  268. TOcApp::EvActivate(bool active)
  269. {
  270.   if (BServiceI)
  271.     BServiceI->OnActivate(active);
  272. }
  273.  
  274. bool
  275. TOcApp::RegisterClass(const string& className, BCID classId, bool multiUse)
  276. {
  277.   // Self-embedding works only if the app is multi-use
  278.   //
  279.   if (BServiceI)
  280.     return HRSucceeded(BServiceI->RegisterClass(OleStr(className.c_str()),
  281.                        this, classId, ToBool(multiUse), ToBool(!multiUse)));
  282.   return false;
  283. }
  284.  
  285. bool
  286. TOcApp::CanClose()
  287. {
  288.   return BServiceI ? HRIsOK(BServiceI->CanClose()) : true;  // there are no servers running
  289. }
  290.  
  291. uint
  292. TOcApp::EnableEditMenu(TOcMenuEnable menuEnable, IBDataConsumer far* ocView)
  293. {
  294.   return BServiceI ? BServiceI->EnableEditMenu(menuEnable, ocView) : 0;
  295. }
  296.  
  297. bool
  298. TOcApp::Browse(TOcInitInfo& init)
  299. {
  300.   return BServiceI ? HRIsOK(BServiceI->Browse(&init)) : false;
  301. }
  302.  
  303. bool
  304. TOcApp::BrowseClipboard(TOcInitInfo& init)
  305. {
  306.   return BServiceI ? HRIsOK(BServiceI->BrowseClipboard(&init)): false;
  307. }
  308.  
  309. bool
  310. TOcApp::Paste(TOcInitInfo& init)
  311. {
  312.   return BServiceI ? HRIsOK(BServiceI->Paste(&init)) : false;
  313. }
  314.  
  315. //
  316. // Copy Selected embedded object
  317. //
  318. bool
  319. TOcApp::Copy(TOcPart* ocPart)
  320. {
  321.   IBPart far* bPartI;
  322.   if (ocPart && SUCCEEDED(ocPart->QueryInterface(IID_IBPart, &(LPVOID)bPartI))) {
  323.     ocPart->Release();
  324.  
  325.     // Copy part with delayed rendering done by Bolero
  326.     //
  327.     return BServiceI ? HRIsOK(BServiceI->Clip(bPartI, true, true, true)) : false;
  328.   }
  329.   return false;
  330. }
  331.  
  332. //
  333. // Copy a selection in server document
  334. //
  335. bool
  336. TOcApp::Copy(TOcDataProvider* ocData)
  337. {
  338.   PRECONDITION(ocData);
  339.   if (BServiceI)
  340.     BServiceI->Clip(0, false, false, false);
  341.   else
  342.     return false;
  343.  
  344. /*
  345.   IBDataProvider far* bDataI;
  346.   if (ocData && SUCCEEDED(ocData->QueryInterface(IID_IBDataProvider, &(LPVOID)bDataI))) {
  347.     ocData->Release();
  348.  
  349.     // Copy part with delayed rendering done by ocDataProvider
  350.     //
  351.     return HRIsOK(BServiceI->Clip(bDataI, true, true, false));
  352.   }
  353.   return false;
  354. */
  355.   return HRIsOK(BServiceI->Clip(ocData, true, true, false));
  356. }
  357.  
  358. //
  359. // Drag a selection
  360. //
  361. bool
  362. TOcApp::Drag(TOcDataProvider* ocData, TOcDropAction inAction, TOcDropAction& outAction)
  363. {
  364.   PRECONDITION(ocData);
  365.   /*
  366.   if (!BServiceI)
  367.     return false;
  368.  
  369.   IBDataProvider far* bDataI;
  370.   if (ocData && SUCCEEDED(ocData->QueryInterface(IID_IBDataProvider, &(LPVOID)bDataI))) {
  371.     ocData->Release();
  372.     return HRSucceeded(BServiceI->Drag(ocData, inAction, &outAction));
  373.   }
  374.   return false;
  375.   */
  376.  
  377.   return BServiceI? HRSucceeded(BServiceI->Drag(ocData, inAction, &outAction)) : false;
  378. }
  379.  
  380. //
  381. // Drag an embedded object
  382. //
  383. bool
  384. TOcApp::Drag(TOcPart* ocPart, TOcDropAction inAction, TOcDropAction& outAction)
  385. {
  386.   IBPart far* bPartI;
  387.   if (ocPart && SUCCEEDED(ocPart->QueryInterface(IID_IBPart, &(LPVOID)bPartI))) {
  388.     ocPart->Release();
  389.     // Drag part with delayed rendering done by Bolero
  390.     //
  391.     return HRSucceeded(BServiceI->Drag(bPartI, inAction, &outAction));
  392.   }
  393.   return false;
  394. //  return BServiceI? HRSucceeded(BServiceI->Drag(ocPart, inAction, &outAction)) : false;
  395. }
  396.  
  397. //
  398. // Open the Convert dialog, and perform the conversion if OK. return true if
  399. // conversion was perfromed successfully.
  400. //
  401. bool
  402. TOcApp::Convert(TOcPart* ocPart, bool b)
  403. {
  404.   PRECONDITION(ocPart);
  405.  
  406.   if (BServiceI == 0)
  407.     return false;
  408.  
  409.   // The Convert dialog is split into two pieces: one to run the dialog box
  410.   // and one to do the actual work. This way, the caller can record the
  411.   // actions of the dialog box for playback later.
  412.   //
  413.   TOcConvertInfo ci;
  414.   if (HRIsOK(BServiceI->ConvertUI(ocPart->GetBPartI(), b, &ci)))
  415.     return HRSucceeded(BServiceI->ConvertGuts(ocPart->GetBPartI(), b, &ci));
  416.  
  417.   return false;
  418. }
  419.  
  420. //----------------------------------------------------------------------------
  421. // IBApplication implementation
  422.  
  423. //
  424. // Return the application's name
  425. //
  426. LPCOLESTR _IFUNC
  427. TOcApp::GetAppName()
  428. {
  429.   return Name;
  430. }
  431.  
  432. TOcHelp _IFUNC
  433. TOcApp::HelpMode(TOcHelp /*newMode*/)
  434. {
  435.   return hlpExit;  // no built in help support
  436. }
  437.  
  438. //
  439. // Insert the container's menus into a provided menubar
  440. //
  441. HRESULT _IFUNC
  442. TOcApp::InsertContainerMenus(HMENU hMenu, TOcMenuWidths far* omw)
  443. {
  444.   PRECONDITION(omw);
  445.   if (!hMenu)
  446.     return HR_NOERROR;
  447.  
  448.   TOcMenuDescr md;
  449.   md.HMenu = hMenu;
  450.   for (int i = 0; i < 6; i++) {
  451.     md.Width[i] = (int)omw->Width[i] = 0;  // make sure the server's are zeroed
  452.     i++;
  453.     md.Width[i] = (int)omw->Width[i];
  454.   }
  455.  
  456.   if (!(bool)ForwardEvent(OC_APPINSMENUS, &md))
  457.     return HR_FAIL;
  458.  
  459.   for (i = 0; i < 6; i++)
  460.     omw->Width[i] = md.Width[i];
  461.  
  462.   return HR_NOERROR;
  463. }
  464.  
  465. //
  466. // Now set the provided menubar into the container's main frame window
  467. //
  468. HRESULT _IFUNC
  469. TOcApp::SetFrameMenu(HMENU hMenu)
  470. {
  471.   TOcMenuDescr md;
  472.   md.HMenu = hMenu;
  473.   return HRFailIfZero((bool)ForwardEvent(OC_APPMENUS, &md));
  474. }
  475.  
  476. //
  477. //
  478. //
  479. HRESULT _IFUNC
  480. TOcApp::Accelerator(MSG far* msg)
  481. {
  482.   PRECONDITION(msg);
  483.  
  484.   return HRFailIfZero((bool)ForwardEvent(OC_APPPROCESSMSG, msg));
  485. }
  486.  
  487. //
  488. // Let BOle know if we (container app) have an accelerator table
  489. //
  490. HRESULT _IFUNC
  491. TOcApp::GetAccelerators(HACCEL far*, int far*)
  492. {
  493.   return HR_FAIL;  // would retrieve or generate an accelerator table here
  494. }
  495.  
  496. //
  497. // Let BOle know if this app can/will accept links
  498. //
  499. HRESULT _IFUNC
  500. TOcApp::CanLink()
  501. {
  502.   return HR_OK;  // return HR_FAIL to disallow Linking
  503. }
  504.  
  505. //
  506. // Let BOle know if this app can/will accept embeddings
  507. //
  508. HRESULT _IFUNC
  509. TOcApp::CanEmbed()
  510. {
  511.   return HR_OK;  // return HR_FAIL to disallow Embedding
  512. }
  513.  
  514. //
  515. // Get and return the app frame's HWND
  516. //
  517. HWND _IFUNC
  518. TOcApp::GetWindow()
  519. {
  520.   return FrameWnd;
  521. }
  522.  
  523. //
  524. // Get client rectangle of app's main frame window
  525. //
  526. HRESULT _IFUNC
  527. TOcApp::GetWindowRect(TRect far* r)
  528. {
  529.   PRECONDITION(r);
  530.  
  531.   return HRFailIfZero((bool)ForwardEvent(OC_APPFRAMERECT, r));
  532. }
  533.  
  534. //
  535. // Return the app's title, same as GetAppName()
  536. //
  537. LPCOLESTR _IFUNC
  538. TOcApp::GetWindowTitle()
  539. {
  540.   return Name;
  541. }
  542.  
  543. //
  544. // The server is asking for space along the app borders to put toolbars, etc.
  545. // This call is used to determine whether the container is willing and able to
  546. // provide a given combination.
  547. //
  548. HRESULT _IFUNC
  549. TOcApp::RequestBorderSpace(const TRect far* space)
  550. {
  551.   return HRFailIfZero((bool)ForwardEvent(OC_APPBORDERSPACEREQ, space));
  552. }
  553.  
  554. //
  555. // Now, actually provide the space along the app frame borders for inplace
  556. // server adornments
  557. //
  558. HRESULT _IFUNC
  559. TOcApp::SetBorderSpace(const TRect far* space)
  560. {
  561.   return HRFailIfZero((bool)ForwardEvent(OC_APPBORDERSPACESET, space));
  562. }
  563.  
  564. //
  565. // Append supplied Ole title to frame's title, saving old title
  566. //
  567. void _IFUNC
  568. TOcApp::AppendWindowTitle(LPCOLESTR /*title*/)
  569. {
  570. }
  571.  
  572. //
  573. // Pass status bar text to container app to have app display it
  574. //
  575. HRESULT _IFUNC
  576. TOcApp::SetStatusText(LPCOLESTR text)
  577. {
  578.   // Convert ole str into ascii
  579.   //
  580.  
  581.   return HRFailIfZero((bool)ForwardEvent(OC_APPSTATUSTEXT, (const char far*)OleStr(text)));
  582. }
  583.  
  584. //
  585. // Respond to let BOle know if our app is MDI or not
  586. //
  587. HRESULT _IFUNC
  588. TOcApp::IsMDI()
  589. {
  590.   // Since this flag is used only to do toolbar negotiation,
  591.   // we're always MDI as far as BOle is concerned.
  592.   //
  593.   return HR_NOERROR;
  594. }
  595.  
  596. //
  597. // The server is entering or leaving a modal state. Keep track so that we don't
  598. // interfere when it is modal.
  599. //
  600. HRESULT _IFUNC
  601. TOcApp::OnModalDialog(BOOL svrModal)
  602. {
  603.   DisableDlgs = (bool)svrModal;
  604.   return HR_NOERROR;
  605. }
  606.  
  607. //
  608. // The in-place server is done. Tell the container to restore its normal UI.
  609. // We can handle the window text here, let the app do the rest.
  610. //
  611. void _IFUNC
  612. TOcApp::RestoreUI()
  613. {
  614.   SetStatusText(0);
  615.   ForwardEvent(OC_APPRESTOREUI);
  616. }
  617.  
  618. //
  619. //
  620. //
  621. void _IFUNC
  622. TOcApp::DialogHelpNotify(TOcDialogHelp help)
  623. {
  624.   ForwardEvent(OC_APPDIALOGHELP, help);
  625. }
  626.  
  627. //
  628. // called by BOle when last embedding is closed
  629. // if that's the only reason the app is up we need to shut ourselves down
  630. //
  631. void _IFUNC
  632. TOcApp::ShutdownMaybe()
  633. {
  634.   TRACEX(OcApp, 1,
  635.          "ShutdownMaybe() on " << (void*)this <<
  636.          " Embedding:" << ToBool(IsOptionSet(amEmbedding)) <<
  637.          " Win:" << hex << (uint)GetWindow());
  638.  
  639.   // Check first to see if TOcApp should initiate a shutdown
  640.   //
  641.   if (ForwardEvent(OC_APPSHUTDOWN) || !GetWindow()) {
  642.     // The server initiated the shutdown
  643.     //
  644.     if (!IsOptionSet(amExeMode)) {  // DLL server
  645.       AddRef();    // prevent destroying ourselves yet
  646.       Registrar.Shutdown(&(IUnknown&)*this, Options);
  647.       Release();   // this should do us in now
  648.     }
  649.   }
  650. }
  651.  
  652. //----------------------------------------------------------------------------
  653.  
  654. uint32
  655. TOcApp::ForwardEvent(int eventId, const void far* param)
  656. {
  657.   if (::IsWindow(GetWindow()))
  658.     return ::SendMessage(GetWindow(), WM_OCEVENT, eventId, (LPARAM)param);
  659.  
  660.   return 0;
  661. }
  662.  
  663. uint32
  664. TOcApp::ForwardEvent(int eventId, uint32 param)
  665. {
  666.   if (::IsWindow(GetWindow()))
  667.     return ::SendMessage(GetWindow(), WM_OCEVENT, eventId, param);
  668.  
  669.   return 0;
  670. }
  671.  
  672. //-----------------------------------------------------------------------------
  673. // TOcClassMgr, IBClassMgr implementation for TOcRegistrar
  674. //
  675.  
  676. class _ICLASS TOcClassMgr : private TUnknown, public IBClassMgr {
  677.   public:
  678.     TOcClassMgr(TComponentFactory cc, uint32 options);
  679.     ~TOcClassMgr();
  680.     ulong _IFUNC   AddRef() ;
  681.     ulong _IFUNC   Release();
  682.  
  683.   private:
  684.     HRESULT _IFUNC QueryInterface(const GUID far& iid, void far*far* iface)
  685.                      {return GetOuter()->QueryInterface(iid, iface);}
  686.     HRESULT _IFUNC ComponentCreate(IUnknown far* far* iface,
  687.                                    IUnknown far* outer, BCID classId);
  688.     HRESULT _IFUNC ComponentInfoGet(IUnknown far* far* info,
  689.                                     IUnknown far* outer, BCID classId);
  690.     // TUnknown virtual overrides
  691.     //
  692.     HRESULT      QueryObject(const IID far& iid, void far* far* iface);
  693.  
  694.     TComponentFactory OcCallback;  // callback for creating component
  695.     uint32    Options;  // options flags from TOcRegistrar
  696.   friend class TOcApp;  // could delegate the interface instead...
  697. };
  698.  
  699. TOcClassMgr::TOcClassMgr(TComponentFactory cc, uint32 options)
  700. :
  701.   OcCallback(cc), Options(options)
  702. {
  703. }
  704.  
  705. TOcClassMgr::~TOcClassMgr()
  706. {
  707. }
  708.  
  709. ulong _IFUNC
  710. TOcClassMgr::AddRef()
  711. {
  712.   return GetOuter()->AddRef();
  713. }
  714.  
  715. ulong _IFUNC
  716. TOcClassMgr::Release()
  717. {
  718.   return GetOuter()->Release();
  719. }
  720.  
  721. //
  722. // IBClassMgr implementation for TOcRegistrar
  723. //
  724. HRESULT _IFUNC
  725. TOcClassMgr::ComponentCreate(IUnknown far* far* retIface, IUnknown far* outer, BCID idClass)
  726. {
  727.   PRECONDITION(idClass && retIface);
  728.  
  729.   *retIface = 0;
  730.   if (!OcCallback)
  731.     return HR_FAIL;
  732.  
  733.   try {
  734.  
  735.     // Test for special condition to force run as an EXE
  736.     //
  737.     void far* v;
  738.     if (outer && !(Options & amExeModule) && outer->QueryInterface(IID_NULL, &v) == HR_NOERROR)
  739.       *retIface = OcCallback(0, Options | amExeMode | amRun, idClass);
  740.     else
  741.       *retIface = OcCallback(outer, Options | amEmbedding, idClass);
  742.     return *retIface ? HR_OK : HR_FAIL;
  743.   }
  744.   catch (...) {  // we can't throw any exception through OLE
  745.     return HR_OUTOFMEMORY;  // probably a resource problem, better error code?
  746.   }
  747. }
  748.  
  749. HRESULT _IFUNC
  750. TOcClassMgr::ComponentInfoGet(IUnknown far* far* info, IUnknown far* /*outer*/,
  751.                               BCID /*idClass*/)
  752. {
  753.   *info = 0;
  754.   return HR_FAIL;
  755. }
  756.  
  757. HRESULT
  758. TOcClassMgr::QueryObject(const IID far& iid, void far* far* iface)
  759. {
  760.   HRESULT hr;
  761.  
  762.   // interfaces
  763.      HRSucceeded(hr = IBClassMgr_QueryInterface(this, iid, iface))
  764.   ;
  765.   return hr;
  766. }
  767.  
  768. //----------------------------------------------------------------------------
  769. // IBClassMgr implementation for TOcApp
  770. //
  771.  
  772. HRESULT _IFUNC
  773. TOcApp::ComponentCreate(IUnknown far* far* retIface, IUnknown far* outer, BCID idClass)
  774. {
  775.   return Registrar.OcClassMgr->ComponentCreate(retIface, outer, idClass);
  776. }
  777.  
  778. HRESULT _IFUNC
  779. TOcApp::ComponentInfoGet(IUnknown far* far* info, IUnknown far* outer, BCID idClass)
  780. {
  781.   return Registrar.OcClassMgr->ComponentInfoGet(info, outer, idClass);
  782. }
  783.  
  784. //-----------------------------------------------------------------------------
  785. // TOcRegistrar
  786. //
  787.  
  788. TOcRegistrar::TOcRegistrar(TRegList& regInfo, TComponentFactory callback,
  789.                            string& cmdLine, TRegLink* linkHead,
  790.                            HINSTANCE hInst)
  791. :
  792.   TRegistrar(*new TAppDescriptor(regInfo, callback, cmdLine, hInst, linkHead)),
  793.   BOleInstance(0),
  794.   BCmI(0),
  795.   OcClassMgr(0),
  796.   AppCount(0)
  797. {
  798.   OcClassMgr = new TOcClassMgr(callback, GetOptions());
  799.   OcClassMgr->AddRef();
  800. }
  801.  
  802. TOcRegistrar::~TOcRegistrar()
  803. {
  804.   if (BCmI)
  805.     BCmI->Release();
  806.   if (OcClassMgr)
  807.     OcClassMgr->Release();
  808.   if (BOleInstance > HINSTANCE(32))
  809.     ::FreeLibrary(BOleInstance);
  810. }
  811.  
  812. //
  813. // Create and return a BOle class manager helper interface with 1 ref on it
  814. //
  815. IBClassMgr*
  816. TOcRegistrar::CreateBOleClassMgr()
  817. {
  818.   if (!BOleInstance)
  819.     LoadBOle();
  820.  
  821.   HRESULT PASCAL FAR _export (*createClassMgr)(IUnknown far* far*,
  822.                                                IUnknown far*, IMalloc far*);
  823.   (FARPROC)createClassMgr = ::GetProcAddress(BOleInstance, BOLEBIND);
  824.   if (createClassMgr) {
  825.  
  826.     // Call thru the exported function to get a BOle class manager
  827.     // Don't aggregate it to anything
  828.     //
  829.     IUnknown*   bcm;
  830.     createClassMgr(&bcm, 0, 0);
  831.     if (bcm) {
  832.       IBClassMgr* bcmi;
  833.       bcm->QueryInterface(IID_IBClassMgr, &(LPVOID)bcmi);
  834.       bcm->Release();
  835.       if (bcmi)
  836.         return bcmi;
  837.     }
  838.   }
  839.   TXObjComp::Throw(TXObjComp::xBOleBindFail);
  840.   return 0; // never reached
  841. }
  842.  
  843. //
  844. // Override TRegistrar's GetFactory to provide additional factory support
  845. // using BOle factories
  846. //
  847. void far*
  848. TOcRegistrar::GetFactory(const GUID& clsid, const GUID far& iid)
  849. {
  850.   void far* factory = TRegistrar::GetFactory(clsid, iid);
  851.   if (factory)
  852.     return factory;
  853.  
  854.   if (!BCmI)
  855.     BCmI = CreateBOleClassMgr();
  856.  
  857.   IUnknown* objFactory = 0;
  858.   IBClass* classMgr    = 0;
  859.  
  860.   TRegLink* link = GetAppDescriptor().GetRegLink(clsid);
  861.   if (!link)
  862.     return 0;
  863.  
  864.   TRegList&   regList = link->GetRegList();
  865.   const char* progid = regList[IsOptionSet(amDebug) ? "debugprogid" : "progid" ];
  866.  
  867.   // Create BoleFactory helper object & init it, giving it our OcClassMgr
  868.   // object to work with
  869.   //
  870.   if (!(HRSucceeded(BCmI->ComponentCreate(&objFactory, 0, cidBOleFactory)) &&
  871.       HRSucceeded(objFactory->QueryInterface(IID_IBClass, &(LPVOID)classMgr)) &&
  872.       HRSucceeded(classMgr->Init(false, OleStr(progid), OcClassMgr, reinterpret_cast<BCID>(link))) &&
  873.       HRSucceeded(classMgr->QueryInterface(iid, &factory)))) {
  874.     if (objFactory)
  875.       objFactory->Release();
  876.     if (classMgr)
  877.       classMgr->Release();
  878.  
  879.     return 0;
  880.   }
  881.  
  882.   return factory;
  883. }
  884.  
  885. bool
  886. TOcRegistrar::CanUnload()
  887. {
  888.   TRACEX(OcDll, 1, "CanUnload() AppCount:" << AppCount);
  889.   return TRegistrar::CanUnload() && AppCount == 0;
  890. }
  891.  
  892. static bool
  893. sGetFileVersionInfo(const char far* fileName, VS_FIXEDFILEINFO& vInfo)
  894. {
  895.   OLECHAR* viBuff;      // version buffer
  896.   uint32   infoSize;    // Size of version info resource in file
  897.  
  898.   // Find out how big the file version info buffer is supposed to be and
  899.   // create a buffer of that size
  900.   //
  901.   uint32 infoHandle;
  902.   if ((infoSize = ::GetFileVersionInfoSize(OleStr(fileName), &infoHandle)) == 0)
  903.     return false;
  904.   viBuff = new OLECHAR[(int)infoSize];
  905.  
  906.   // Copy the file version info buffer from the file into viBuff
  907.   //
  908.   if (::GetFileVersionInfo(OleStr(fileName), 0, infoSize, viBuff)) {
  909.  
  910.     // Perform some magic on the phantom buffer to get an actual structure with
  911.     // the version information
  912.     //
  913.     uint vInfoLen;
  914.     VS_FIXEDFILEINFO far* vInfoPtr;
  915.     if (::VerQueryValue(viBuff, "\\", &(void far*)vInfoPtr, &vInfoLen)) {
  916.       vInfo = *vInfoPtr;
  917.       delete [] viBuff;
  918.       return true;
  919.     }
  920.   }
  921.   delete [] viBuff;
  922.   return false;
  923. }
  924.  
  925. //
  926. // Dynamically load the OcOle Dll, get the one entry point that we need &
  927. // make the class manager object that we use
  928. //
  929. void
  930. TOcRegistrar::LoadBOle()
  931. {
  932.   // Check BOle DLL existance & version first, failing if it is incompatible
  933.   // (old)
  934.   //
  935.   char name[30];
  936.   OFSTRUCT ofs;
  937.   ofs.cBytes = sizeof ofs;
  938.  
  939. #if defined(BI_PLAT_WIN32)
  940.   bool winNT = !ToBool(::GetVersion()&0x80000000);
  941.   if (winNT) // NT platform
  942.   {
  943.     lstrcpy(name, BOLEDLLW);
  944.  
  945.     // Try the ANSI dll if couldn't find Unicode version
  946.     if (::OpenFile(name, &ofs, OF_EXIST) == HFILE_ERROR)
  947.       lstrcpy(name, BOLEDLL);
  948.   }
  949.   else
  950. #endif
  951.     lstrcpy(name, BOLEDLL);
  952.  
  953.   if (::OpenFile(name, &ofs, OF_EXIST) >= 0) {
  954.     VS_FIXEDFILEINFO vInfo;
  955.     if (!sGetFileVersionInfo(name, vInfo) ||
  956.         vInfo.dwFileVersionMS < BOLE_FILEVER_MS ||
  957.           vInfo.dwFileVersionMS == BOLE_FILEVER_MS &&
  958.           vInfo.dwFileVersionLS < BOLE_FILEVER_LS)
  959.       TXObjComp::Throw(TXObjComp::xBOleVersFail);
  960.  
  961.     BOleInstance = ::LoadLibrary(ofs.szPathName);
  962.   }
  963.  
  964.   // If we failed to load the DLL, throw a general cannot-load exception.
  965.   // Otherwise get the class manager interface
  966.   //
  967.   if (BOleInstance <= HINSTANCE(32))
  968.     TXObjComp::Throw(TXObjComp::xBOleLoadFail);
  969. }
  970.  
  971. //-----------------------------------------------------------------------------
  972. // TOcFormatName
  973. //
  974.  
  975. TOcFormatName::TOcFormatName()
  976. {
  977. }
  978.  
  979. TOcFormatName::TOcFormatName(const char far* name, const char far* resultName,
  980.                              const char far* id)
  981. :
  982.   Name(name),
  983.   ResultName(resultName),
  984.   Id(id)
  985. {
  986. }
  987.  
  988. //----------------------------------------------------------------------------
  989. // TOcNameList
  990. //
  991.  
  992. TOcNameList::TOcNameList()
  993. :
  994.   TICVectorImp<TOcFormatName>(15, 3)
  995. {
  996. }
  997.  
  998. TOcNameList::~TOcNameList()
  999. {
  1000.   Clear();
  1001. }
  1002.  
  1003. //
  1004. // Find the format name with the corresponding id
  1005. //
  1006. TOcFormatName*
  1007. TOcNameList::operator [](char far* id)
  1008. {
  1009.   for (uint i = 0; i < Count(); i++) {
  1010.     TOcFormatName* formatName = (*this)[i];
  1011.     if (strcmp(formatName->GetId(), id) == 0)
  1012.       return formatName;
  1013.   }
  1014.  
  1015.   return 0;
  1016. }
  1017.  
  1018. //----------------------------------------------------------------------------
  1019. // TOcInitInfo
  1020. //
  1021.  
  1022. TOcInitInfo::TOcInitInfo(IBContainer far* container)
  1023. :
  1024.   How(ihEmbed),
  1025.   Where(iwNew),
  1026.   Container(container),
  1027.   HIcon(0),
  1028.   Storage(0)
  1029. {
  1030. }
  1031.  
  1032. TOcInitInfo::TOcInitInfo(TOcInitHow how, TOcInitWhere where, IBContainer far* container)
  1033. :
  1034.   How(how),
  1035.   Where(where),
  1036.   Container(container),
  1037.   HIcon(0),
  1038.   Storage(0)
  1039. {
  1040. }
  1041.  
  1042.