home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / owlsrc.pak / MODULE.CPP < prev    next >
C/C++ Source or Header  |  1997-07-23  |  11KB  |  429 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // (C) Copyright 1991, 1994 by Borland International, All Rights Reserved
  4. //
  5. //   Implementation of class TModule.  TModule defines the
  6. //   basic behavior for OWL libraries and applications.
  7. //----------------------------------------------------------------------------
  8. #pragma hdrignore SECTION
  9. #include <owl/owlpch.h>
  10. #include <owl/module.h>
  11. #include <owl/appdict.h>
  12.  
  13. extern uint _OWLDATA GetWindowPtrMsgId;  // in applicat.cpp
  14.  
  15.  
  16. #if !defined(SECTION) || SECTION == 1
  17.  
  18. //----------------------------------------------------------------------------
  19.  
  20. //
  21. // implementation of Constructors for a TModule object
  22. //
  23.  
  24. //
  25. // Construct a TModule that is an alias for a DLL. TModule will load & free
  26. // the DLL if shouldLoad is true. If shouldLoad is false, then the HInstance
  27. // must be set some time later using InitModule()
  28. //
  29. TModule::TModule(const char far* name, bool shouldLoad)
  30. {
  31.   if (shouldLoad) {
  32.     HInstance = ::LoadLibrary(name);
  33.     if (HInstance <= HINSTANCE(32))
  34.       THROW( TXInvalidModule() );
  35.   }
  36.   else {
  37.     HInstance = 0;
  38.   }
  39.  
  40.   ShouldFree = shouldLoad;
  41.   Name = strnewdup(name);
  42.   lpCmdLine = 0;
  43. }
  44.  
  45. //
  46. // Construct a TModule that is an alias for an already loaded DLL or program
  47. // with an HInstance available. Name is optional & can be 0. No cmdLine is
  48. // setup
  49. //
  50. TModule::TModule(const char far* name, HINSTANCE hInstance)
  51. {
  52.   PRECONDITION(hInstance > HINSTANCE(32));
  53.   HInstance = hInstance;
  54.   ShouldFree = false;
  55.   Name = strnewdup(name);
  56.   lpCmdLine = 0;
  57. }
  58.  
  59. //
  60. // Construct a TModule for an Owl Program via TApplication. InitModule is
  61. // called from here to initialize HInstance & the CmdLine
  62. //
  63. TModule::TModule(const char far* name, HINSTANCE hInstance,
  64.                  const char far* cmdLine)
  65. {
  66.   HInstance = 0;
  67.   ShouldFree = false;
  68.   Name = strnewdup(name);
  69.   lpCmdLine = 0;
  70.   if (hInstance)
  71.     InitModule(hInstance, cmdLine);
  72. }
  73.  
  74. //
  75. // Destruct a TModule, freeing the instance if appropriate, and deleting
  76. // new'd strings
  77. //
  78. TModule::~TModule()
  79. {
  80.   if (ShouldFree)
  81.     ::FreeLibrary(HInstance);
  82.   delete [] Name;
  83.   delete [] lpCmdLine;
  84. }
  85.  
  86. void
  87. TModule::SetName(const char far* name)
  88. {
  89.   delete [] Name;
  90.   Name = strnewdup(name);
  91. }
  92.  
  93. //
  94. // perform initialization of modules cmd line copy, and get proc
  95. // instance handles for the standard procs.
  96. //
  97. void
  98. TModule::InitModule(HINSTANCE hInstance, const char far* cmdLine)
  99. {
  100.   SetInstance(hInstance);
  101.  
  102. #if defined(BI_PLAT_WIN32)
  103.   //
  104.   // Win32 prepends the full application path to the command line arguments
  105.   // skip over this "extra" argument for 16-bit compatibility
  106.   // _argc and _argv do the correct processing, _argv[0] being the pathname
  107.   //
  108.   if (cmdLine)
  109.     while (*cmdLine && *cmdLine++ != ' ')
  110.       ;
  111. #endif
  112.  
  113.   if (cmdLine)
  114.     lpCmdLine = strnewdup(cmdLine);
  115.  
  116.   // Register a system-wide "GetWindowPtr" message as "GetWindowPtr(_hInstance)"
  117.   // Each running copy of ObjectWindows will get a unique message Id
  118.   //
  119.   if (!GetWindowPtrMsgId) {
  120.     const char msgTemplate[] = "GetWindowPtr(%X)";
  121.     char msgName[sizeof(msgTemplate) + 8];
  122.     wsprintf(msgName, msgTemplate, unsigned(_hInstance));
  123.     GetWindowPtrMsgId = ::RegisterWindowMessage(msgName);
  124.     CHECK(GetWindowPtrMsgId);
  125.   }
  126. }
  127.  
  128. //
  129. // Replaceable exception handler; may be redefined to process OWL exceptions
  130. // if canResume is false, then the user doesn't have the option of ignoring
  131. //
  132. int
  133. TModule::Error(xmsg& x, unsigned captionResId, unsigned promptResId)
  134. {
  135.   char cbuf[80];
  136.   char pbuf[80];
  137.  
  138.   if (!captionResId)
  139.     captionResId = IDS_UNHANDLEDXMSG;
  140.   return HandleGlobalException(x,
  141.     LoadString(captionResId, cbuf, sizeof(cbuf)) ? cbuf : 0,
  142.     promptResId ?
  143.       (LoadString(promptResId, pbuf, sizeof(cbuf)) ? pbuf : "OK to Resume?")
  144.       : 0);
  145. }
  146.  
  147. //
  148. // Set the instance handle for a module that does not yet have one. Cannot
  149. // be called on a module that already has an instance handle.
  150. //
  151. void
  152. TModule::SetInstance(HINSTANCE hInstance)
  153. {
  154.   PRECONDITION(!ShouldFree && !HInstance);
  155.   HInstance = hInstance;
  156. }
  157.  
  158. //
  159. // LoadString replacements which do not generated debug warning output
  160. //
  161. #if defined(BI_PLAT_WIN32)
  162.  typedef WCHAR* TResText;
  163.  typedef WCHAR* TResCount;
  164. #else
  165.  typedef char far* TResText;
  166.  typedef uint8 far* TResCount;
  167. #endif
  168.  
  169. int
  170. TModule::LoadString(uint id, char far* buf, int bufSize) const
  171. {
  172.   uint len = 0;
  173.   HRSRC     resHdl;
  174.   HGLOBAL   glbHdl;
  175.   TResText  resData;
  176.  
  177.   if ((resHdl = FindResource(id/16+1, RT_STRING)) != 0
  178.    && (glbHdl = LoadResource(resHdl)) != 0) {
  179.     if ((resData = (TResText)LockResource(glbHdl)) != 0) {
  180.       for (int cnt = id % 16; len = *(TResCount)resData++, cnt--; resData += len)
  181.         ;
  182.       if (len != 0) {
  183.         if (len >= bufSize)
  184.           len = bufSize-1;
  185.         for (cnt = len; cnt--; *buf++ = (char)*resData++)
  186.           ;
  187.         *buf = 0;
  188.       }
  189.       UnlockResource(glbHdl);
  190.     }
  191.     FreeResource(glbHdl);
  192.     if (len)
  193.       return len;
  194.   }
  195.  
  196.   if (::Module != this)                   // look in OWL module if different
  197.     return ::Module->LoadString(id, buf, bufSize);
  198.  
  199.   if (bufSize)
  200.     *buf = 0;  // make empty string just in case caller doesn't check return
  201.   return 0;    // indicate string not found
  202. }
  203.  
  204. string
  205. TModule::LoadString(uint id) const
  206. {
  207.   uint len = 0;
  208.   HRSRC     resHdl;
  209.   HGLOBAL   glbHdl;
  210.   TResText  resData;
  211.   string    retString;
  212.  
  213.   if ((resHdl = FindResource(id/16+1, RT_STRING)) != 0
  214.    && (glbHdl = LoadResource(resHdl)) != 0) {
  215.     if ((resData = (TResText)LockResource(glbHdl)) != 0) {
  216.       for (int cnt = id % 16; len = *(TResCount)resData++, cnt--; resData += len)
  217.         ;
  218.       if (len != 0) {
  219. #if (0) // This is dangerous unless string is changed to handle non-terminated
  220.         // char arrays
  221.         //
  222.         retString.append(resData, 0, len);
  223. #else
  224.         retString.resize(len);
  225.         int i = 0;
  226.         for (cnt = len; cnt--; retString[i++] = (char)*resData++)
  227.           ;
  228. #endif
  229.       }
  230.       UnlockResource(glbHdl);
  231.     }
  232.     FreeResource(glbHdl);
  233.     if (len)
  234.       return retString;
  235.   }
  236.  
  237.   if (::Module != this)                   // look in OWL module if different
  238.     return ::Module->LoadString(id);
  239.  
  240.   return retString;    // empty if string not found
  241. }
  242.  
  243. //----------------------------------------------------------------------------
  244.  
  245. #include <owl/applicat.h>
  246.  
  247. //
  248. // obsolete error handler--use Error(xmsg&,...) instead
  249. //
  250. void
  251. TModule::Error(int errorCode)
  252. {
  253.   char       errorStr[51];
  254.   TModule*   module = GetApplicationObject();
  255.  
  256.   wsprintf(errorStr,
  257.            "Error received: error code = %d\nOK to proceed?",
  258.            errorCode);
  259.  
  260.   if (::MessageBox(0, errorStr, module ? module->GetName() : Name,
  261.                    MB_ICONSTOP | MB_YESNO | MB_TASKMODAL) == IDNO)
  262.   #if defined(BI_PLAT_WIN32)
  263.     ::PostThreadMessage(GetCurrentThreadId(), WM_QUIT, 0, 0);
  264.   #else
  265.     ::PostAppMessage(GetCurrentTask(), WM_QUIT, 0, 0);
  266.   #endif
  267. }
  268.  
  269. //----------------------------------------------------------------------------
  270. //
  271. // Exception class
  272. //
  273.  
  274. TModule::TXInvalidModule::TXInvalidModule() : TXOwl(IDS_INVALIDMODULE)
  275. {
  276. }
  277.  
  278. TXOwl*
  279. TModule::TXInvalidModule::Clone()
  280. {
  281.   return new TXInvalidModule(*this);
  282. }
  283.  
  284. void
  285. TModule::TXInvalidModule::Throw()
  286. {
  287.   THROW( *this );
  288. }
  289.  
  290. #endif
  291. #if !defined(SECTION) || SECTION == 2
  292.  
  293. //----------------------------------------------------------------------------
  294. // TModule streaming
  295. //
  296.  
  297. IMPLEMENT_STREAMABLE(TModule);
  298.  
  299. void*
  300. TModule::Streamer::Read(ipstream& is, uint32 /*version*/) const
  301. {
  302.   TModule* o = GetObject();
  303.   is >> (TResId&)o->Name;
  304.   is >> (TResId&)o->lpCmdLine;
  305.   is >> o->ShouldFree;
  306.   if (o->ShouldFree)
  307.     o->HInstance = ::LoadLibrary(o->Name);
  308.  
  309.   return o;
  310. }
  311.  
  312. void
  313. TModule::Streamer::Write(opstream& os) const
  314. {
  315.   TModule* o = GetObject();
  316.   os << TResId(o->Name);
  317.   os << TResId(o->lpCmdLine);
  318.   os << o->ShouldFree;
  319. }
  320.  
  321. #endif
  322. #if !defined(SECTION) || SECTION == 3
  323.  
  324. //----------------------------------------------------------------------------
  325. //
  326. // Entry (& exit) functions for Owl in a DLL
  327. //
  328.  
  329. #if defined(_BUILDOWLDLL)
  330.  
  331. //
  332. // TModule derived class to facilitate streaming pointer to the OWL Library
  333. // the OWL module must be streamed by reference before any pointers to it
  334. // the following code simply prevents writing data back over the OWL module 
  335. //
  336.  
  337. class _OWLCLASS TObjectWindowsLibrary : public TModule {
  338.  public:
  339.   TObjectWindowsLibrary(HINSTANCE hInst) : TModule("ObjectWindowsDLL", hInst){}
  340.   DECLARE_STREAMABLE(_OWLCLASS, TObjectWindowsLibrary, 1);
  341. };
  342.  
  343. IMPLEMENT_STREAMABLE1(TObjectWindowsLibrary, TModule);
  344.  
  345. void*
  346. TObjectWindowsLibrary::Streamer::Read(ipstream&, uint32) const
  347. {
  348.   return GetObject();
  349. }
  350.  
  351. void
  352. TObjectWindowsLibrary::Streamer::Write(opstream&) const
  353. {
  354. }
  355.  
  356. //
  357. // Global pointer to this module
  358. //
  359. TModule* Module = 0;
  360.  
  361. #if defined(BI_PLAT_WIN32)
  362.  
  363. static int  Attaches = 0;  // Win32s doesn't have per-instance data-- keep
  364.                            // track of number of attached processes
  365.  
  366. int WINAPI
  367. DllEntryPoint(HINSTANCE hInstance, uint32 reason, void*)
  368. {
  369.   switch (reason) {
  370.     case DLL_PROCESS_ATTACH: {
  371.       if (!Attaches) {
  372.         ::Module = new TObjectWindowsLibrary(hInstance);
  373.       }
  374.       Attaches++;
  375.       break;
  376.     }
  377.     case DLL_PROCESS_DETACH: {
  378.       Attaches--;
  379.       if (!Attaches)
  380.         delete ::Module;
  381.       break;
  382.     }
  383.   }
  384.   return true;
  385. }
  386.  
  387. #else  // !defined(BI_PLAT_WIN32)
  388.  
  389. //
  390. // Entry point for the Owl DLL itself
  391. //
  392. int FAR PASCAL
  393. LibMain(HINSTANCE   hInstance,
  394.         uint16    /*wDataSeg*/,
  395.         uint16    /*cbHeapSize*/,
  396.         char far* /*lpCmdLine*/)
  397. {
  398.   //
  399.   // Allocate the TModule object for the Owl DLL. The RTL makes sure that
  400.   // the memory allocated is GMEM_SHARE.
  401.   //
  402.   ::Module = new TObjectWindowsLibrary(hInstance);
  403.  
  404.   return Module->Status == 0;
  405. }
  406.  
  407. int
  408. FAR PASCAL
  409. WEP(int /*bSystemExit*/)
  410. {
  411.   delete ::Module;
  412.   return 1;
  413. }
  414.  
  415. #endif  // defined(BI_PLAT_WIN32)
  416. #endif  // defined(_BUILDOWLDLL)
  417. #endif  // SECTION == 3
  418.  
  419. #if !defined(SECTION) || SECTION == 4
  420. //
  421. // Inserter for formated output of instance handle
  422. //
  423. ostream& _OWLFUNC
  424. operator <<(ostream& os, const TModule& m)
  425. {
  426.   return os << hex << uint(m.HInstance);
  427. }
  428. #endif //section 4
  429.