//----------------------------------------------------------------------------
// ObjectWindows
// Copyright (c) 1991, 1996 by Borland International, All Rights Reserved
//
/// \file
/// Implementation of class TModule. TModule defines the base behavior for
/// OWL libraries and applications.
//----------------------------------------------------------------------------
 
#if defined(__BORLANDC__)
# pragma option -w-inl // Disable warning "Functions containing 'statement' is not expanded inline".
#endif
 
#include <owl/pch.h>
 
#include <owl/defs.h>
#include <owl/module.h>
#include <owl/appdict.h>
#include <owl/applicat.h>
#include <owl/pointer.h>
#include <stdio.h>
#include <winnls.h>
#include <owl/template.h>
 
#if defined(BI_MULTI_THREAD_RTL)
#include <owl/thread.h>
#endif
 
#include <owl/window.h>
#include <owl/framewin.h>
 
#if defined(BI_COMP_MSC)
#include <new.h>
#endif
 
#if OWL_STACKWALKER
# include "stackwalker.h"
#endif
 
#include <array>
 
long TlsAddRefs();
long TlsRelease();
 
#if defined(__BORLANDC__)
# pragma option -w-ccc // Disable "Condition is always true/false"
#endif
 
#if defined(_MSC_VER)
# pragma warning(disable: 4996) // Turn off deprecation warnings (triggered by GetVersion/GetVersionEx).
#endif
 
namespace owl {
 
OWL_DIAGINFO;
DIAG_DECLARE_GROUP(OwlApp);        // General Application diagnostic group
 
//
// Global message id for GetWindowPtr call defined in owl.cpp
//
extern _OWLDATA(uint) GetWindowPtrMsgId;
 
} // OWL namespace
 
using namespace std;
 
namespace owl {
 
//
/// Returns the class name in string form.
/// If the class name is represented by an atom, then the Windows API function GetAtomName is
/// called to look up the string associated with the atom.
//
auto TWindowClassName::GetString() const -> tstring
{
  auto getAtomName = [](ATOM a) -> tstring
  {
    auto b = array<tchar, 256>{};
    const auto n = ::GetAtomName(a, b.data(), static_cast<int>(b.size()));
    return tstring(b.data(), n);
  };
  return IsString() ? tstring{GetPointerRepresentation()} : getAtomName(GetAtom());
}
 
//----------------------------------------------------------------------------
 
//
// TSystemMessage
// ~~~~~~~~~~~~~~
//
TSystemMessage::TSystemMessage()
{
  Error = ::GetLastError();
  Init(LangNeutral);
}
 
//
//
//
TSystemMessage::TSystemMessage(uint32 error, TLangId langId)
{
  Error = error;
  ::SetLastError(Error);
  Init(langId);
}
 
//
//
//
int TSystemMessage::MessageBox(TWindow* win, const tstring& msg, const tstring& title, uint flags) const
{
  flags |= MB_SYSTEMMODAL;
 
  tstring message = msg;
  message += Message;
  TApplication* appl;
  if(!win && (appl = OWLGetAppDictionary().GetApplication(0))!=0 && appl->GetMainWindow())
    win = appl->GetMainWindow();
  if(win)
    return win->MessageBox(message.c_str(), title, flags);
  return ::MessageBox(0, message.c_str(), title.c_str(), flags);
}
 
//
//
//
void TSystemMessage::Init(TLangId langId)
{
  LPVOID ptr = 0;
  if(::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                NULL, Error, langId, (LPTSTR)&ptr, 0, NULL) != 0)
  {
    Message = (LPTSTR)ptr;
    LocalFree(ptr); // free the memory allocated by FormatMessage
  }
  else{
    tchar buffer[MAX_PATH];
    wsprintf(buffer, _T("Error: %#X occurred (no further info)"), Error);
    Message = buffer;
  }
}
//----------------------------------------------------------------------------
 
//} // OWL namespace
 
// Implement
//////////////////////////////////////////////////////////////////////////////////////////////////
// multithread support
/// \cond
class __TModuleList {
  public:
    static TModule*  Next(TModule* module);
    static bool      Find(TModule* module);
    static void      Add(TModule* module);
    static void      Remove(TModule* module);
    static TModule*  FindResModule(TResId id, TResId type);
 
    static TPtrArray<TModule*>* ModuleArray;
 
#if defined(BI_MULTI_THREAD_RTL)
    static TMRSWSection*  Lock;
#endif
 
};
 
TPtrArray<TModule*>* __TModuleList::ModuleArray = 0;
#if defined(BI_MULTI_THREAD_RTL)
TMRSWSection*  __TModuleList::Lock = 0;
#endif
 
#if defined(BI_MULTI_THREAD_RTL)
#define LOCKLIST(s) TMRSWSection::TLock __lock(*__TModuleList::Lock, s)
#else
#define LOCKLIST(s)
#endif
//
TModule* __TModuleList::Next(TModule* module)
{
  if(!ModuleArray)
    return 0;
  LOCKLIST(true);
  if(!module){
    return (*ModuleArray)[0];
  }
  else{
    for(uint i = 0; i < ModuleArray->Size(); i++){
      if(module == (*ModuleArray)[i])
        return (i+1 < ModuleArray->Size()) ? (*ModuleArray)[i+1] : 0;
    }
  }
  return 0;
}
//
void __TModuleList::Add(TModule* module)
{
  if(Find(module))
    return;
 
  if(!ModuleArray)
  {
#if defined(BI_MULTI_THREAD_RTL)
    Lock = new TMRSWSection;
#endif
    ModuleArray = new TPtrArray<TModule*>;
  }
  {
    LOCKLIST(false);
 
    // If there is another object, but with the same hInstance, replace it.
    // This usualy happens when the global module is created and added to the list,
    // and afterwards the TApplication-derived object with the same hInstance is created
    for (uint i = 0; i < ModuleArray->Size(); i++)
    {
      if (module->GetHandle() == (*ModuleArray)[i]->GetHandle())
      {
        (*ModuleArray)[i] = module;
        return;
      }
    }
 
 
    ModuleArray->AddAt(module,0);
  }
}
//
void __TModuleList::Remove(TModule* module)
{
  if(!Find(module))
    return;
 
  PRECONDITION(ModuleArray);
  {
    LOCKLIST(false);
    ModuleArray->DetachItem(module);
    if(ModuleArray->Empty())
    {
      delete ModuleArray;
      ModuleArray = 0;
    }
  }
#if defined(BI_MULTI_THREAD_RTL)
  if(!ModuleArray){
    delete Lock;
    Lock = 0;
  }
#endif
}
//
bool __TModuleList::Find(TModule* module)
{
  if(!ModuleArray)
    return false;
  LOCKLIST(true);
 
  for (uint i = 0; i < ModuleArray->Size(); i++){
    if (module == (*ModuleArray)[i])
      return true;
  }
  return false;
}
//
TModule* __TModuleList::FindResModule(TResId id, TResId type)
{
  if(!ModuleArray)
    return 0;
 
  LOCKLIST(true);
 
  TApplication* appl = OWLGetAppDictionary().GetApplication(0);
  TLangId langId = appl ? appl->GetLangId() : LangNeutral;
  TPtrArray<TModule*>::Iterator Iter1(*ModuleArray);
  while(Iter1){
    if((*Iter1)->FindResourceEx(id, type, langId))
      return *Iter1;
    Iter1++;
  }
 
  TPtrArray<TModule*>::Iterator Iter(*ModuleArray);
  while(Iter){
    if((*Iter)->FindResource(id, type))
      return *Iter;
    Iter++;
  }
  return 0;
}
 
/// \endcond
 
///////////////////////////////////////////////////////////////////////////
//
TModule* TModule::NextModule(TModule* module)
{
  return __TModuleList::Next(module);
}
 
//namespace owl {
 
//
// Implementation of Constructors for a TModule object
//
 
//
/// Constructs a TModule object that is used as an alias for a DLL. If shouldLoad is
/// true, TModule will automatically load and free the DLL. If shouldLoad is false,
/// then the HInstance needs to be set later using InitModule.
///
/// "mustLoad" determines if a load failure should cause an exception throw
//
TModule::TModule(const tstring& name, bool shouldLoad, bool mustLoad, bool addToList)
{
  if (shouldLoad) {
    TErrorMode loadMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
    Handle = ::LoadLibrary(name.c_str());
    if (Handle <= HINSTANCE(HINSTANCE_ERROR) && mustLoad) {
      TRACEX(OwlApp, 0, _T("Unable to load DLL '") << name.c_str() << _T('\''));
      TXInvalidModule::Raise(name);  // !CQ use a better exception. This is for windows
    }
  }
  else {
    Handle = 0;
  }
 
  ShouldFree = shouldLoad;
  SetName(name);
 
  //
  // Add Module  into global Array
  //
  if(addToList)
    __TModuleList::Add(this);
}
 
//
/// Constructs a TModule object that is an alias for an already loaded DLL or
/// program with an available HInstance. When the TModule is destructed, the
/// instance isn't automatically freed. name, which is optional, can be 0.
/// No cmdLine is set up.
/// If null-pointer is passed for name, and the module handle is valid, the name is retrieved using GetModuleFileName.
//
TModule::TModule(LPCTSTR name, HINSTANCE hInstance, bool addToList)
{
  PRECONDITION(hInstance > HINSTANCE(HINSTANCE_ERROR));
  Handle = hInstance;
  ShouldFree = false;
  SetName(name);
 
  //
  // Add Module  into global Array
  //
  if (addToList)
    __TModuleList::Add(this);
}
 
//
/// String-aware overload.
/// If an empty name is passed, and the module handle is valid, the name is retrieved using GetModuleFileName.
//
TModule::TModule(const tstring& name, HINSTANCE hInstance, bool addToList)
{
  PRECONDITION(hInstance > HINSTANCE(HINSTANCE_ERROR));
  Handle = hInstance;
  ShouldFree = false;
  SetName(name);
 
  //
  // Add Module  into global Array
  //
  if(addToList)
    __TModuleList::Add(this);
}
 
//
/// Constructs a TModule object for an ObjectWindows DLL or program from within
/// LibMain or WinMain. Calls InitModule to initialize hInstance and cmdLine.
/// If null-pointer is passed for name, and the module handle is valid, the name is retrieved using GetModuleFileName.
//
TModule::TModule(LPCTSTR name, HINSTANCE hInstance, const tstring& cmdLine, bool addToList)
{
  Handle = 0;
  ShouldFree = false;
  if (hInstance)
    InitModule(hInstance, cmdLine);
  SetName(name);
 
  //
  // Add Module  into global Array
  //
  if(addToList)
    __TModuleList::Add(this);
}
 
//
/// String-aware overload.
/// If an empty name is passed, and the module handle is valid, the name is retrieved using GetModuleFileName.
//
TModule::TModule(const tstring& name, HINSTANCE hInstance, const tstring& cmdLine, bool addToList)
{
  Handle = 0;
  ShouldFree = false;
  if (hInstance)
    InitModule(hInstance, cmdLine);
  SetName(name);
 
  //
  // Add Module  into global Array
  //
  if (addToList)
    __TModuleList::Add(this);
}
 
//
/// Destructs a TModule, freeing the instance if appropriate, and deleting
/// new'd strings
//
TModule::~TModule()
{
  if (ShouldFree && Handle > HINSTANCE(HINSTANCE_ERROR))
    ::FreeLibrary(Handle);
 
  //
  // Detach Module from global ModuleArray
  //
  __TModuleList::Remove(this);
}
 
//
/// Global  search for  resources
//
TModule*
TModule::FindResModule(TResId id, TResId type)
{
  return __TModuleList::FindResModule(id, type);
}
 
//
/// Accessor function that sets the name of the module.
/// If null-pointer is passed, and the module handle is valid, the name is retrieved using GetModuleFileName.
//
void
TModule::SetName(LPCTSTR name)
{
  Name = name ? name :
    (Handle > HINSTANCE(HINSTANCE_ERROR)) ? GetModuleFileName() :
    _T("");
}
 
//
/// String-aware overload.
/// If an empty string is passed, and the module handle is valid, the name is retrieved using GetModuleFileName.
//
void
TModule::SetName(const tstring& name)
{
  Name = (name.length() == 0 && Handle > HINSTANCE(HINSTANCE_ERROR)) ?
    GetModuleFileName() : name;
}
 
//
/// Performs any instance initialization necessary for the module. If the module
/// cannot be created, a TXInvalidModule exception is thrown.
///
/// Copies cmd line, and gets proc
/// instance handles for the standard procs.
//
 
#if !defined(BI_COMP_GNUC)
#pragma warn -par
#endif
 
void
TModule::InitModule(THandle hInstance, const tstring& cmdLine)
{
  SetHandle(hInstance);
 
#if defined(BI_COMP_GNUC)
  // Borland removes the first element of argv (program name) from
  // owl::CmdLine somehow ("the RTL takes care of this" above), but
  // g++ does not. Modifying the cmdLine argument won't have any effect
  // because it's const and is passed as string::c_str().
  char const* cmdLine = TApplication::GetCmdLine().c_str();
  if(cmdLine){
    while (*cmdLine && *cmdLine++ != _T(' '))
      ;
    TApplication::GetCmdLine() = cmdLine;
  }
#endif
 
  // Register a system-wide "GetWindowPtr" message as GetWindowPtr(hInstance)
  // Each running copy of ObjectWindows will get a unique message Id
  // instance of OWL library. !!!
  if (!GetWindowPtrMsgId) {
    const tchar msgTemplate[] = _T("GetWindowPtr(%X)");
    tchar msgName[COUNTOF(msgTemplate) + 8];
    wsprintf(msgName, msgTemplate, static_cast<uint>(reinterpret_cast<UINT_PTR>(hInstance)));
    GetWindowPtrMsgId = ::RegisterWindowMessage(msgName);
    CHECK(GetWindowPtrMsgId);
  }
}
 
#if !defined(BI_COMP_GNUC)
#pragma warn .par
#endif
 
//
/// Replaceable exception handler; may be redefined to process OWL exceptions
/// if canResume is false, then the user doesn't have the option of ignoring
//
/// Called when fatal exceptions occur, Error takes an xmsg exception
/// object, a resource ID for a message box caption, and an optional resource ID for
/// a user prompt. By default, Error calls HandleGlobalException with the xmsg
/// object and the strings obtained from the resources. An application (derived from
/// TApplication which is derived from TModule) can reimplement this function to
/// provide alternative behavior.
/// A nonzero status code is returned to indicate that an error condition is to be
/// propagated; a zero status indicates that the condition has been handled and that
/// it is OK to proceed. ObjectWindows uses this status code inside its message loop
/// to allow the program to resume. The global error handler (defined in except.h),
/// which displays the message text, is
/// \code
/// int _OWLFUNC HandleGlobalException(xmsg& x, char* caption, char* canResume);
/// \endcode
int
TModule::Error(TXBase& x, unsigned captionResId, unsigned promptResId)
{
  tchar cbuf[80];
  tchar pbuf[80];
 
  if (!captionResId)
    captionResId = IDS_UNHANDLEDXMSG;
  return HandleGlobalException(x,
    LoadString(captionResId, cbuf, 80) ? cbuf : 0,
    promptResId ?
      (LoadString(promptResId, pbuf, 80) ? pbuf : _T("OK to Resume?"))
      : 0);
}
 
//
/// For use with CopyText.
//
struct TGetModuleFileName
{
  const TModule& module;
  TGetModuleFileName(const TModule& m) : module(m) {}
 
  int operator()(LPTSTR buf, int buf_size) const
  {
    int n = module.GetModuleFileName(buf, buf_size);
    WARN(n == buf_size, _T("TModule::GetModuleFileName truncated the result."));
    return n;
  }
};
 
//
/// String-aware overload
//
tstring TModule::GetModuleFileName() const
{
  return CopyText(_MAX_PATH, TGetModuleFileName(*this));
}
 
//
/// Set the instance handle for a module that does not yet have one. Cannot
/// be called on a module that already has an instance handle.
//
void
TModule::SetHandle(HINSTANCE hInstance)
{
  PRECONDITION(!ShouldFree && !Handle);
  Handle = hInstance;
}
 
//
// LoadString replacements which do not generated debug warning output
//
 typedef WCHAR* TResText;
 typedef WCHAR* TResCount;
 
//
// Wrapper for loading a string resource.
//
/// Loads a string resource identified by id into the buffer pointed to by
/// buff. maxChars indicates the size of the buffer to which the zero-terminated
/// string is copied. A string longer than the length specified in maxChars is
/// truncated. The return value is the number of characters copied into the buffer,
/// or 0 if the string resource does not exist.
int
TModule::LoadString(uint id, LPTSTR buf, int bufSize) const
{
#ifdef MAINWIN
  int resource = ::LoadString( GetInstance(), id, buf, bufSize);
  if (resource)
    return resource;
#else /// MAINWIN
  uint len = 0;
  HRSRC     resHdl;
  HGLOBAL   glbHdl;
  TResText  resData;
 
  TApplication* appl = OWLGetAppDictionary().GetApplication(0);
  resHdl = FindResourceEx(id/16+1, RT_STRING, appl ? appl->GetLangId() : LangNeutral);
  if(!resHdl)
    resHdl = FindResource(id/16+1, RT_STRING);
  if(resHdl != 0){
    if((glbHdl = LoadResource(resHdl)) != 0) {
      if ((resData = (TResText)LockResource(glbHdl)) != 0) {
        // get pointer to our string
        int cnt;
        for (cnt = id % 16; len = *(TResCount)resData++, cnt--; resData += len)
          ;
        if (len != 0) {
#  if defined(UNICODE)
          if (len >= uint(bufSize))
            len = bufSize-1;
          wmemset(buf, 0, bufSize);
          ::_tcsncpy(buf, resData, len);
          //::_tcscpy(buf, resData); // Ma, 09.10.2003 string too long
#  else
          len = ::WideCharToMultiByte(CP_ACP, 0, resData, len, buf, bufSize, 0, 0);
          if (len > 0)
            buf[len] = 0;
#  endif
        }
      }
      FreeResource(glbHdl);
      if (len)
        return len;
    }
  }
  else{
    // if not found look in Module List
    TModule* module = TModule::FindResModule(id/16+1, RT_STRING);
    if (module)
      return module->LoadString(id, buf, bufSize);
  }
#endif //else not MAINWIN
  if (bufSize)
    *buf = 0;  // make empty string just in case caller doesn't check return
  return 0;    // indicate string not found
}
 
//
// Wrapper for loading a string resource.
//
/// Loads a string resource identified by id
//
#ifdef UNIX
tstring
TModule::LoadString(uint id) const
{
 
// Added by Val Ovechkin 7:18 PM 6/11/98
  char str[1024] = "<empty>";
  int res = ::LoadString( GetInstance(), id, str, sizeof str );
  if( !res ) str[0] = 0;
  return tstring( str );
 
 
  uint len = 0;
  HRSRC     resHdl;
  HGLOBAL   glbHdl;
  TResText  resData;
  tstring    retString;
 
  if ((resHdl = FindResource(id/16+1, RT_STRING)) != 0
   && (glbHdl = LoadResource(resHdl)) != 0) {
    if ((resData = (TResText)LockResource(glbHdl)) != 0) {
      int cnt;
      for (cnt = id % 16; len = *(TResCount)resData++, cnt--; resData += len)
        ;
      if (len != 0) {
#if (0) // This is dangerous unless string is changed to handle non-terminated
        // char arrays
        //
        retString.append(resData, 0, len);
#else
        int n = ::WideCharToMultiByte(CP_ACP, 0, resData, len, 0, 0, 0, 0);
        TAPointer<char> buf = new char[n+1];
        len = ::WideCharToMultiByte(CP_ACP, 0, resData, len, buf, n+1, 0, 0);
  #if   0
        retString.resize(len+1);
        uint i;
        for (i = 0; i < len; i++)
          retString[i] = (char)buf[i];
        retString[i] = 0;
  #else
        // The string object does not need the terminating null of C-strings
        //
        retString.resize(len);
        uint i;
        for (i = 0; i < len; i++)
          retString[i] = (char)buf[i];
  #endif
#endif
      }
    }
    FreeResource(glbHdl);
    if (len)
      return retString;
  }
 
  if (&GetGlobalModule() != this)                   // look in OWL module if different
    return GetGlobalModule().LoadString(id);
 
  return retString;    // empty if string not found
}
 
#else
 
/// Loads a string resource identified by id
tstring
TModule::LoadString(uint id) const
{
  int len    = 0;
  HRSRC     resHdl;
  HGLOBAL   glbHdl;
  TResText  resData;
   tstring retString;
 
  TApplication* appl = OWLGetAppDictionary().GetApplication(0);
  resHdl = FindResourceEx(id/16+1, RT_STRING, appl ? appl->GetLangId() : LangNeutral);
  if(!resHdl)
    resHdl = FindResource(id/16+1, RT_STRING);
  if (resHdl != 0){
    if((glbHdl = LoadResource(resHdl)) != 0){
      if ((resData = (TResText)LockResource(glbHdl)) != 0) {
        int cnt;
        for (cnt = id % 16; len = *(TResCount)resData++, cnt--; resData += len)
          ;
        if (len != 0) {
#if (0)   // This is dangerous unless string is changed to handle non-terminated
          // char arrays
          retString.append(resData, 0, len);
#else
#    if defined(UNICODE)
          // The string object does not need the terminating null of C-strings
          retString.resize(len); // Ma, 09.10.2003 string is not terminated!
 
          for (int i = 0; i < len; i++)
            retString[i] = resData[i];
#    else
          int n = ::WideCharToMultiByte(CP_ACP, 0, resData, len, 0, 0, 0, 0);
          TAPointer<tchar> __ClnObj(new tchar[n+1]);
          tchar* buf = __ClnObj;
          len = ::WideCharToMultiByte(CP_ACP, 0, resData, len, buf, n+1, 0, 0);
          // The string object does not need the terminating null of C-strings
          retString.resize(len);
          int i;
          for (i = 0; i < len; i++)
            retString[i] = buf[i];
#    endif
#endif
        }
      }
      if (len)
        return retString;
    }
  }
  else{
    // if not found look in Module List
    TModule* module = TModule::FindResModule(id/16+1, RT_STRING);
    if (module)
      return module->LoadString(id);
  }
 
  return retString;    // empty if string not found
}
#endif
 
 
 
//
/// Wrapper for the Windows API.
//
/// Loads the bitmap resource specified by id. If the bitmap cannot be found,
/// LoadBitmap returns 0.
//
HBITMAP TModule::LoadBitmap(TResId id) const
{
  PRECONDITION(Handle > HINSTANCE(HINSTANCE_ERROR));
#if 0
  HRSRC    resHdl;
  HGLOBAL glbHdl;
  HBITMAP hBitmap=0;
 
  TApplication* appl = OWLGetAppDictionary().GetApplication(0);
  resHdl = FindResourceEx(id, RT_BITMAP, appl ? appl->GetLangId() : LangNeutral);
 
  if(resHdl){
    if((glbHdl = LoadResource(resHdl)) !=0)
      hBitmap = (HBITMAP)LockResource(glbHdl);
  }
#else
  HBITMAP hBitmap = ::LoadBitmap(Handle, id);
#endif
  WARNX(OwlApp, !hBitmap, 0, _T("Bitmap resource not found Id:") << id);
 
  if(!hBitmap){// if not found look in Module List
     TModule* module = TModule::FindResModule(id, RT_BITMAP);
     if(module)
       return module->LoadBitmap(id);
  }
 
  CHECKX(hBitmap,_T("Bitmap resource not found even in module list."));
  return hBitmap;
}
//
/// Wrapper for the Windows API.
//
/// Loads the accelerator table resource specified by id. LoadAccelerators loads the
/// table only if it has not been previously loaded. If the table has already been
/// loaded, LoadAccelerators returns a handle to the loaded table.
//
HACCEL TModule::LoadAccelerators(TResId id) const
{
  PRECONDITION(Handle > HINSTANCE(HINSTANCE_ERROR));
 
#if 0
  HRSRC resHdl;
  HGLOBAL glbHdl;
 
  HACCEL hAccel = 0;
 
  TApplication* appl = OWLGetAppDictionary().GetApplication(0);
  resHdl = FindResourceEx(id, RT_ACCELERATOR, appl ? appl->GetLangId() : LangNeutral);
  if(!resHdl)
    resHdl = FindResource(id, RT_ACCELERATOR);
  if(resHdl){
    if((glbHdl = LoadResource(resHdl)) !=0)
      hAccel = (HACCEL)LockResource(glbHdl);
  }
#else
  HACCEL hAccel = ::LoadAccelerators(Handle, id);
#endif
  WARNX(OwlApp,!hAccel,0,_T("Accelerator resource not found") << id);
 
  if(!hAccel){ // if not found look in Module List
    TModule* module = TModule::FindResModule(id, RT_ACCELERATOR);
     if(module)
       return module->LoadAccelerators(id);
  }
 
  WARNX(OwlApp,!hAccel,0,_T("Accelerator resource not found even in module list") << id);
  //CHECKX(hAccel,_T("Accelerator resource not found even in module list."));
 
  return hAccel;
}
//----------------------------------------------------------------------------
 
//
/// Wrapper for the Windows API.
//
/// Loads the menu resource indicated by id into memory. If the menu resource cannot
/// be found, LoadMenu returns 0.
//
HMENU TModule::LoadMenu(TResId id) const
{
  PRECONDITION(Handle > HINSTANCE(HINSTANCE_ERROR));
#if 0
  HRSRC resHdl;
  HGLOBAL glbHdl;
   HMENU hMenu = 0;
  TApplication* appl = OWLGetAppDictionary().GetApplication(0);
  resHdl = FindResourceEx(id, RT_MENU, appl ? appl->GetLangId() : LangNeutral);
  if(!resHdl)
    resHdl = FindResource(id, RT_MENU);
  if(resHdl){
    if((glbHdl = LoadResource(resHdl)) !=0)
      hMenu = (HMENU)LockResource(glbHdl);
  }
#else
  HMENU hMenu = ::LoadMenu(Handle, id);
#endif
  WARNX(OwlApp,!hMenu,0,_T("Menu resource not found") << id);
 
  if (!hMenu){ // if not found look in Module List
    TModule* module = TModule::FindResModule(id, RT_MENU);
     if(module)
       return module->LoadMenu(id);
  }
 
  CHECKX(hMenu,_T("Menu resource not found even in module list."));
  return hMenu;
}
//----------------------------------------------------------------------------
 
//
/// Wrapper for the Windows API.
//
/// Loads the cursor resource specified by id into memory and returns a handle to
/// the cursor resource. If the cursor resource cannot be found or identifies a
/// resource that is not a cursor, LoadCursor returns 0.
//
HCURSOR TModule::LoadCursor(TResId id) const
{
  PRECONDITION(Handle > HINSTANCE(HINSTANCE_ERROR));
#if 0
  HRSRC resHdl;
  HGLOBAL glbHdl;
   HCURSOR hCursor = 0;
 
  TApplication* appl = OWLGetAppDictionary().GetApplication(0);
  resHdl = FindResourceEx(id, RT_CURSOR, appl ? appl->GetLangId() : LangNeutral);
 
  if(resHdl){
    if((glbHdl = LoadResource(resHdl)) !=0)
      hCursor = (HCURSOR)LockResource(glbHdl);
  }
#else
  HCURSOR hCursor = ::LoadCursor(Handle, id);
#endif
  WARNX(OwlApp,!hCursor,0,_T("Cursor resource not found") << id);
 
  if (!hCursor){ // if not found look in Module List
    TModule* module = TModule::FindResModule(id, RT_CURSOR);
     if(module)
       return module->LoadCursor(id);
  }
 
  CHECKX(hCursor,_T("Cursor resource not found even in module list."));
  return hCursor;
}
 
//----------------------------------------------------------------------------
//
/// Wrapper for the Windows API.
//
/// Loads the icon resource indicated by the parameter, name, into memory. LoadIcon
/// loads the icon only if it has not been previously loaded. If the icon resource
/// cannot be found, LoadIcon returns 0.
///
/// LoadIcon can be used to load a predefined Windows icon if name points to one of
/// the Windows IDI_XXXX values.
//
HICON TModule::LoadIcon(TResId name) const
{
  PRECONDITION(Handle > HINSTANCE(HINSTANCE_ERROR));
#if 0
  HRSRC resHdl;
  HGLOBAL glbHdl;
   HICON hIcon = 0;
 
  TApplication* appl = OWLGetAppDictionary().GetApplication(0);
  resHdl = FindResourceEx(TResId(name), RT_ICON, appl ? appl->GetLangId() : LangNeutral);
 
  if(resHdl){
    if((glbHdl = LoadResource(resHdl)) !=0)
      hIcon = (HICON)LockResource(glbHdl);
  }
#else
  HICON hIcon = ::LoadIcon(Handle, name);
#endif
  WARNX(OwlApp,!hIcon,0,_T("Icon resource not found") << name);
 
  if (!hIcon){ // if not found look in Module List
    TModule* module = TModule::FindResModule(name, RT_ICON);
     if(module)
       return module->LoadIcon(name);
  }
 
  CHECKX(hIcon,_T("Icon resource not found even in module list"));
  return hIcon;
}
 
//----------------------------------------------------------------------------
//
/// Loads the given HTML resource and returns it as a narrow string.
/// It is left to the client to detect the character set and encoding of the contents.
/// If the resource is not found in this module, the module list is tried.
/// If that also fails, an assertion exception is thrown in diagnostics mode.
/// In non-diagnostics mode, an empty string is returned on failure.
//
string TModule::LoadHtml(TResId id) const
{
  PRECONDITION(Handle > HINSTANCE(HINSTANCE_ERROR));
  HRSRC r = FindResourceEx(id, RT_HTML);
  WARNX(OwlApp, !r, 0, _T("HTML resource not found: ") << id);
  if (!r)
  {
    // The resource was not found in this module, so try the module list.
    //
    TModule* module = FindResModule(id, RT_HTML);
    CHECKX(module, _T("HTML resource not found even in the module list."));
    return module ? module->LoadHtml(id) : string();
  }
  HGLOBAL g = LoadResource(r); CHECK(g);
  const char* p = static_cast<const char*>(LockResource(g)); // Note: No unlocking needed (see API doc).
  return string(p, p + SizeofResource(r));
}
 
//----------------------------------------------------------------------------
// Module entry dynamic binding base class
 
//
/// Functional-style overload.
/// Throws TXOwl on error.
//
auto TModule::GetClassInfo(TWindowClassName name) const -> WNDCLASS
{
  auto w = WNDCLASS{};
  const auto r = GetClassInfo(name, &w);
  if (!r) throw TXOwl{_T("TModule::GetClassInfo failed")};
  return w;
}
 
//
/// Returns `true` if the given window class has been registered.
/// \sa GetClassInfo
//
auto TModule::IsRegisteredClass(TWindowClassName name) const -> bool
{
  auto w = WNDCLASS{};
  return GetClassInfo(name, &w) == true;
}
 
//----------------------------------------------------------------------------
 
//
/// Constructs a Module entry object given a narrow Windows resource identifier.
/// The resource identifier encodes either a function name or a function ordinal
/// for one of the exported functions in the module.
//
TModuleProc::TModuleProc(const TModule& module, TNarrowResId id)
{
  Proc = module.GetProcAddress(id);
  if (!Proc) // Handle failure.
  {
    tstring msg = id.IsInt() ?
      TXOwl::MakeMessage(IDS_INVALIDMODULEORD, id.GetInt()) :
      TXOwl::MakeMessage(IDS_INVALIDMODULEFCN, id.GetString());
    msg += module.GetName();  // Just tack on the module name.
    TXOwl::Raise(msg);
  }
}
 
//----------------------------------------------------------------------------
// Wrappers for Windows API
//
 
 
  static const tchar userStr[] = _T("USER32");
# if defined(UNICODE)
    static const char LoadIconStr[] = "LoadIconW";
    static const char GetClassInfoStr[] = "GetClassInfoW";
    static const char GetMenuStringStr[]= "GetMenuStringW";
# else
    static const char LoadIconStr[] = "LoadIconA";
    static const char GetClassInfoStr[] = "GetClassInfoA";
    static const char GetMenuStringStr[]= "GetMenuStringA";
# endif
 
static const char GetMenuStateStr[] = "GetMenuState";
static const char DestroyIconStr[] = "DestroyIcon";
 
//
// Returns TModule object wrapping the handle of the USER module
//
TModule&
TUser::GetModule()
{
  static TModule userModule(userStr, ::GetModuleHandle(userStr),false);
  return userModule;
}
 
//
// Invokes 'LoadIcon' indirectly
//
HICON
TUser::LoadIcon(HINSTANCE p1, LPCTSTR p2)
{
  static TModuleProc2<HICON, HINSTANCE, LPCTSTR>
         loadIcon(GetModule(), LoadIconStr);
  return loadIcon(p1, p2);
}
 
//
// Invokes 'DestroyIcon' indirectly
//
BOOL
TUser::DestroyIcon(HICON p1)
{
  static TModuleProc1<BOOL, HICON> destroyIcon(GetModule(), DestroyIconStr);
  return destroyIcon(p1);
}
 
//
// Invokes 'GetClassInfo' indirectly
//
BOOL
TUser::GetClassInfo(HINSTANCE p1, LPCTSTR p2, LPWNDCLASS p3)
{
  static TModuleProc3<BOOL, HINSTANCE, LPCTSTR, LPWNDCLASS>
         getClassInfo(GetModule(), GetClassInfoStr);
  return getClassInfo(p1, p2, p3);
}
 
//
// Invokes 'GetMenuString' indirectly
//
int
TUser::GetMenuString(HMENU p1, UINT p2, LPTSTR p3, int p4, UINT p5)
{
  static TModuleProc5<int, HMENU, uint, LPTSTR, int, int>
         getMenuString(GetModule(), GetMenuStringStr);
  return getMenuString(p1, p2, p3, p4, p5);
}
 
//
// Invokes 'GetMenuState' indirectly
//
UINT
TUser::GetMenuState(HMENU p1, UINT p2, UINT p3)
{
  static TModuleProc3<UINT, HMENU, UINT, UINT>
         getMenuState(GetModule(), GetMenuStateStr);
  return getMenuState(p1, p2, p3);
}
 
/////////////////////////////////////////////////////////////
// VERSION.DLL or VER.DLL
  static const tchar verStr[] = _T("VERSION.DLL");
# if defined(UNICODE)
    static const char GetFileVersionInfoStr[] = "GetFileVersionInfoW";
    static const char GetFileVersionInfoSizeStr[] = "GetFileVersionInfoSizeW";
    static const char VerQueryValueStr[]= "VerQueryValueW";
    static const char VerLanguageNameStr[]  = "VerLanguageNameW";
# else
    static const char GetFileVersionInfoStr[] = "GetFileVersionInfoA";
    static const char GetFileVersionInfoSizeStr[] = "GetFileVersionInfoSizeA";
    static const char VerQueryValueStr[]= "VerQueryValueA";
    static const char VerLanguageNameStr[]  = "VerLanguageNameA";
# endif
 
//
// Returns TModule object wrapping the handle of the VERSION.DLL module
//
TModule&
TVersion::GetModule()
{
  static TModule verModule(verStr, true, true, false);
  return verModule;
}
 
//
// Invokes 'GetFileVersionInfo' indirectly
//
BOOL
TVersion::GetFileVersionInfo(LPTSTR p1, DWORD p2, DWORD p3, LPVOID p4)
{
  static TModuleProc4<BOOL,LPTSTR,DWORD,DWORD,LPVOID>
         getFileVersionInfo(GetModule(), GetFileVersionInfoStr);
  return getFileVersionInfo(p1, p2, p3, p4);
}
 
//
// Invokes 'GetFileVersionInfoSize' indirectly
//
DWORD
TVersion::GetFileVersionInfoSize(LPTSTR p1, LPDWORD p2)
{
  static TModuleProc2<DWORD,LPTSTR,LPDWORD>
         getFileVersionInfoSize(GetModule(), GetFileVersionInfoSizeStr);
  return getFileVersionInfoSize(p1, p2);
}
 
//
// Invokes 'VerQueryValue' indirectly
//
BOOL
TVersion::VerQueryValue(const LPVOID p1,LPTSTR p2,LPVOID p3, uint * p4)
{
  static TModuleProc4<BOOL,const LPVOID,LPTSTR,LPVOID,uint *>
         verQueryValue(GetModule(), VerQueryValueStr);
  return verQueryValue(p1, p2, p3, p4);
}
 
//
// Invokes 'VerLanguageName' indirectly
//
DWORD
TVersion::VerLanguageName(DWORD p1, LPTSTR p2, DWORD p3)
{
  static TModuleProc3<DWORD,DWORD,LPTSTR,DWORD>
         verLanguageName(GetModule(), VerLanguageNameStr);
  return verLanguageName(p1, p2, p3);
}
 
/////////////////////////////////////////////////////////////
//
//  Delay loading OLE libraries
//
static const tchar oleStr[]            = _T("OLE32.DLL");
static const tchar oleAutStr[]          = _T("OLEAUT32.DLL");
 
static const char CoCreateInstanceStr[]  = "CoCreateInstance";
static const char SysFreeStringStr[]    = "SysFreeString";
static const char SysStringLenStr[]      = "SysStringLen";
static const char SysAllocStringStr[]    = "SysAllocString";
 
//
// Returns TModule object wrapping the handle of the OLE32.DLL/COMPOBJ.DLL module
//
TModule&
TOle::GetModule()
{
  static TModule oleModule(oleStr, true, true, false);
  return oleModule;
}
 
//
// Invokes 'CoCreateInstance' indirectly
//
HRESULT
TOle::CoCreateInstance(REFCLSID p1, LPUNKNOWN p2, DWORD p3, REFIID p4, LPVOID* p5)
{
  static TModuleProc5<HRESULT,REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID*>
         coCreateInstance(GetModule(), CoCreateInstanceStr);
  return coCreateInstance(p1, p2, p3, p4, p5);
};
 
//
// Returns TModule object wrapping the handle of the OLE32.DLL/COMPOBJ.DLL module
//
TModule&
TOleAuto::GetModule()
{
  static TModule oleautoModule(oleAutStr, true, true, false);
  return oleautoModule;
}
 
//
// Invokes 'SysFreeString' indirectly
//
HRESULT
TOleAuto::SysFreeString(BSTR p1)
{
  static TModuleProc1<HRESULT,BSTR>
         sysFreeString(GetModule(), SysFreeStringStr);
  return sysFreeString(p1);
}
 
//
// Invokes 'SysStringLen' indirectly
//
UINT
TOleAuto::SysStringLen(BSTR p1)
{
  static TModuleProc1<UINT,BSTR>
         sysStringLen(GetModule(), SysStringLenStr);
  return sysStringLen(p1);
}
 
 
//
// Invokes 'SysAllocString' indirectly
//
BSTR
TOleAuto::SysAllocString(const OLECHAR * p1)
{
  static TModuleProc1<BSTR,const OLECHAR *>
         sysAllocString(GetModule(), SysAllocStringStr);
  return sysAllocString(p1);
}
 
//----------------------------------------------------------------------------
//
// Exception class
//
 
//
/// Creates the Invalid Module exception.
//
TXInvalidModule::TXInvalidModule(const tstring& name)
:
  TXOwl(MakeMessage(IDS_INVALIDMODULE, name))
{
}
 
//
/// Creates a copy of the exception
//
TXInvalidModule*
TXInvalidModule::Clone()
{
  return new TXInvalidModule(*this);
}
 
 
//
/// Throws the exception
//
void
TXInvalidModule::Throw()
{
  throw *this;
}
 
//
/// Throws the exception
//
void
TXInvalidModule::Raise(const tstring& name)
{
  TXInvalidModule(name).Throw();
}
} // OWL namespace
 
 
namespace owl {
 
 
//----------------------------------------------------------------------------
// TModule streaming
//
 
IMPLEMENT_STREAMABLE(TModule);
 
#if OWL_PERSISTENT_STREAMS
 
//
/// Extracts the module object from the persistent stream.
//
void*
TModule::Streamer::Read(ipstream& is, uint32 /*version*/) const
{
  TModule* o = GetObject();
  is >> o->Name;
  is >> o->ShouldFree;
  if (o->ShouldFree)
    o->Handle = ::LoadLibrary(o->Name.c_str());
 
  return o;
}
 
//
/// Writes the module into a persistent stream.
//
void
TModule::Streamer::Write(opstream& os) const
{
  TModule* o = GetObject();
  os << o->Name;
  os << o->ShouldFree;
}
 
#endif
 
} // OWL namespace
 
 
//----------------------------------------------------------------------------
//
// Entry (& exit) functions for Owl in a DLL
//
 
#if defined(_BUILDOWLDLL)
 
namespace owl {
 
void InitGlobalModule(HINSTANCE hInstance)
{
  if (Module == NULL)
  {
    tchar buffer[_MAX_PATH];
    GetModuleFileName(hInstance, buffer, _MAX_PATH);
    static TModule module(buffer, hInstance);
    Module = &module;
    TRACEX(OwlApp, 0, "Global Module " << hInstance << ", " << buffer << " created");
  }
 
}
 
TModule& GetGlobalModule()
{
  if (Module == NULL)
  {
    HINSTANCE hInstance = ::GetModuleHandle(NULL);
    InitGlobalModule(hInstance);
  }
 
  return *Module;
}
 
//
/// TModule derived class to facilitate streaming pointer to the OWL Library
/// the OWL module must be streamed by reference before any pointers to it
/// the following code simply prevents writing data back over the OWL module
//
class _OWLCLASS TObjectWindowsLibrary : public TModule {
 public:
  TObjectWindowsLibrary(HINSTANCE hInst) : TModule(_T("ObjectWindowsDLL"), hInst){}
  DECLARE_STREAMABLE(_OWLCLASS, TObjectWindowsLibrary, 1);
};
 
 
IMPLEMENT_STREAMABLE1(TObjectWindowsLibrary, TModule);
 
#  if OWL_PERSISTENT_STREAMS
 
//
/// Reads the object from the persistent stream.
//
void*
TObjectWindowsLibrary::Streamer::Read(ipstream&, uint32) const
{
  return GetObject();
}
 
//
/// Writes the object into a persistent stream.
//
void
TObjectWindowsLibrary::Streamer::Write(opstream&) const
{
}
 
#endif
 
 
//JJH - following stuff is defined in global.cpp, we do not need it here.
//Jogy - it is needed in both places for DLL builds.
//VH - Reason is that the VC and BC build script doesn't link global.obj for the DLL itself, only for the import lib.
//
# if !defined(WINELIB)
extern TModule* Module = 0;   // Global Module ptr in each DLL/EXE
# endif // !WINELIB
 
} // OWL namespace
 
#  if !defined(BI_COMP_BORLANDC) && !defined(BI_COMP_GNUC)
 
int __cdecl xnew_handler(size_t) {throw std::bad_alloc(); return 0;}
 
static void init_new_handler(void)
{
  _set_new_handler(&xnew_handler);
}
 
#  endif // !defined(BI_COMP_BORLANDC) && !defined(BI_COMP_GNUC)
 
 
extern "C" BOOL WINAPI RawDllMain(HINSTANCE, DWORD dwReason, LPVOID);
#    if defined(BI_COMP_BORLANDC)
extern "C" BOOL (WINAPI* _pRawDllMain)(HINSTANCE, DWORD, LPVOID) = RawDllMain;
#    else
extern "C" BOOL (WINAPI* _pRawDllMain)(HINSTANCE, DWORD, LPVOID); //JJH split this to declaration and initialization
BOOL (WINAPI* _pRawDllMain)(HINSTANCE, DWORD, LPVOID) = &RawDllMain;
#    endif
 
extern "C"
//#    if !defined(BI_COMP_MSC)
//BOOL WINAPI RawDllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID)
//#    else
BOOL WINAPI RawDllMain(HINSTANCE, DWORD dwReason, LPVOID)
//#    endif
{
  if (dwReason == DLL_PROCESS_ATTACH){
#if OWL_STACKWALKER
    //Start gathering memory leaks:
    InitAllocCheck(ACOutput_XML);
#endif
 
#    ifdef _UNICODE
    // give error message and exit if running Unicode on non-Unicode system
    if (::GetVersion() & 0x80000000){
      // Note: this message is for programmers who can read english
      ::MessageBoxA(NULL,
        "This application or DLL can not be loaded "
        "on Windows 95 or on Windows 3.1.  It takes advantage "
        "of Unicode features only available on Windows NT.",
        "OWL Runtime Module", MB_ICONSTOP|MB_OK);
      return FALSE; // and fail
    }
#    endif
 
 
    //
    ///! SetErrorMode(GetErrorMode(0)|SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
    // add a reference to thread local storage data
    TlsAddRefs();
 
  }
  else if (dwReason == DLL_PROCESS_DETACH){
    TlsRelease();
#if OWL_STACKWALKER
    //Stop gathering memory leaks:
    DeInitAllocCheck();
#endif
  }
  return TRUE;    // ok
}
 
#if !defined(BI_COMP_BORLANDC)
#if defined(WINELIB) //JJH
extern "C"
#endif
BOOL WINAPI
DllMain(HINSTANCE hInstance, DWORD reason, LPVOID lpreserved)
#else
int WINAPI
DllEntryPoint(HINSTANCE hInstance, owl::uint32 reason, void*)
#endif
{
  switch (reason) {
    case DLL_PROCESS_ATTACH: {
#if !defined(BI_COMP_BORLANDC) && !defined(BI_COMP_GNUC)
        init_new_handler();
#endif
 
//JJH Ok, we don't need to initialize owl::Module, since TApplication object
//    does this for us, see also applicat.cpp:420, applicat.h:132
//#if !defined(WINELIB)
        owl::Module = new owl::TObjectWindowsLibrary(hInstance);
//#endif
      break;
    }
    case DLL_PROCESS_DETACH: {
      break;
    }
  }
  return true;
}
 
/////////////////////////////////////////////////////////////////////////////
//
// Here VC bug with vector constructor
//
// Special code to wire up vector deleting destructors
// TODO: Jogy - check if this is needed with modern VC++ compilers
#if defined(BI_COMP_MSC)
static void _OwlForceVectorDelete()
{
#ifdef _DEBUG
  PRECONDITION(false);  // never called
#endif
 
  new owl::TPoint[2];
  new owl::TPointF[2];
  new owl::TPointL[2];
  new owl::TRect[2];
  new owl::TSize[2];
  new owl::TColor[2];
  new owl::TMenu[2];
  new owl::TResId[2];
  new owl::TFileTime[2];
  new owl::TSystemTime[2];
}
#endif // BI_COM_MSC
#else  // else _BUILDOWLDLL
////////////////////////////////////////////////////////////////////////////////////////
// static lib????
/////////////////////////////////////
#if defined(BI_COMP_BORLANDC)
//
// Doesn't work here -> moved to winmain
//
//
// NOTE: We use priority 31 to come just before/after ctr/dtr of global
//       objects (which are assigned a priorority of 32)
//
void __initOWL()
{
  TlsAddRefs();
}
#pragma startup __initOWL 31
 
//
void __termOWL()
{
  TlsRelease();
}
#pragma exit __termOWL 31
 
//
#elif defined(BI_COMP_MSC)
 
int  __cdecl xnew_handler(size_t) { throw std::bad_alloc(); return 0;}
 
static void init_new_handler(void)
{
//#ifdef __EDG__
//  std::set_new_handler(&xnew_handler);
//#else
  _set_new_handler(&xnew_handler);
//#endif
}
 
// force initialization early
#pragma warning(disable: 4073)
#pragma init_seg(lib)
 
static void __initOWL()
{
  //_hInstance = GetModuleHandleA(NULL);
  TlsAddRefs();
 
  init_new_handler();
 
#if defined(BI_DBCS_SUPPORT)
//  _setmbcp(_MB_CP_ANSI); // check
#endif
}
 
//
void _cdecl __termOWL()
{
  TlsRelease();
}
 
static char __initOWLS = (char)(__initOWL(), atexit(&__termOWL));
 
//
#elif defined(BI_COMP_GNUC)
 
// //JJH
//#if defined(WINELIB)
//void __termOWL()
//#else
void _cdecl __termOWL()
//#endif
{
  TlsRelease();
}
 
static void __initOWL()
{
  TlsAddRefs();
}
 
// //JJH
//#if defined(WINELIB)
//typedef void (__attribute__((__stdcall__)) *STDCALL_FN)();
//static char __initOWLS = (char)(__initOWL(),atexit((STDCALL_FN)__termOWL));
//#else
static char __initOWLS = (char)(__initOWL(),atexit(__termOWL));
//#endif
 
#else
#error Unknown compiler
#endif
 
 
#endif  // defined(_BUILDOWLDLL)
 
namespace owl {
//
// Inserter for formated output of instance handle
//
_OWLCFUNC(ostream&)
operator <<(ostream& os, const TModule& m)
{
  return os << static_cast<void*>(m.Handle);
}
} // OWL namespace
 
 
/* ========================================================================== */
 

V581 The conditional expressions of the 'if' statements situated alongside each other are identical. Check lines: 797, 803.

V581 The conditional expressions of the 'if' statements situated alongside each other are identical. Check lines: 875, 881.

V581 The conditional expressions of the 'if' statements situated alongside each other are identical. Check lines: 913, 919.

V581 The conditional expressions of the 'if' statements situated alongside each other are identical. Check lines: 954, 960.

V803 Decreased performance. In case 'Iter1' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.

V803 Decreased performance. In case 'Iter' is iterator it's more effective to use prefix form of increment. Replace iterator++ with ++iterator.