//----------------------------------------------------------------------------
// ObjectComponents
// Copyright (c) 1994, 1996 by Borland International, All Rights Reserved
//
/// \file
///   OLE Registration implementation
//----------------------------------------------------------------------------
#include <ocf/pch.h>
#include <ocf/ocreg.h>
#include <ocf/appdesc.h>
#include <owl/pointer.h>
#include <owl/module.h>
#include <shellapi.h>
#include <string.h>
#include <stdlib.h>
 
namespace ocf {
 
DIAG_DEFINE_GROUP_INIT(OWL_INI, OcfDll, 1, 0);
DIAG_DECLARE_GROUP(OcfRefCount);
 
using namespace owl;
 
#if defined(BI_APP_DLL)
  extern TRegistrar* DllRegistrar;
#endif
 
//----------------------------------------------------------------------------
// Internal registration template table and registration item key table
//
 
//
/// Registration template table, ordering determines sequence of registration.
///  Also, these are all based on HKEY_CLASSES_ROOT
/// \note the parameter table is dependent on template indices in this table
//
static const _TCHAR* OcRegTemplates[] = {
/* 001 */ _T("CLSID\\<clsid>\\<serverctx>Server32 = <debugger> <path> <cmdline><extraopt>"),
/* 002 */ _T("CLSID\\<clsid>\\ProgID = <progid>"),
/* 003 */ _T("CLSID\\<clsid> = <description>"),
/* 004 */ _T("CLSID\\<clsid>\\DefaultIcon = <path>,<iconindex>"),
/* 005 */ _T("CLSID\\<clsid>\\InprocHandler32 = <handler>"),
/* 006 */ _T("<progid>\\CLSID = <clsid>"),
/* 007 */ _T("<progid> = <description>"),
 
/* 010 */ _T("<progid>\\protocol\\StdFileEditing\\verb\\0 = <verb0>"),
/* 011 */ _T("<progid>\\protocol\\StdFileEditing\\verb\\1 = <verb1>"),
/* 012 */ _T("<progid>\\protocol\\StdFileEditing\\verb\\2 = <verb2>"),
/* 013 */ _T("<progid>\\protocol\\StdFileEditing\\verb\\3 = <verb3>"),
/* 014 */ _T("<progid>\\protocol\\StdFileEditing\\verb\\4 = <verb4>"),
/* 015 */ _T("<progid>\\protocol\\StdFileEditing\\verb\\5 = <verb5>"),
/* 016 */ _T("<progid>\\protocol\\StdFileEditing\\verb\\6 = <verb6>"),
/* 017 */ _T("<progid>\\protocol\\StdFileEditing\\verb\\7 = <verb7>"),
 
/* 020 */ _T("CLSID\\<clsid>\\Verb\\0 = <verb0>,<verb0opt>"),
/* 021 */ _T("CLSID\\<clsid>\\Verb\\1 = <verb1>,<verb1opt>"),
/* 022 */ _T("CLSID\\<clsid>\\Verb\\2 = <verb2>,<verb2opt>"),
/* 023 */ _T("CLSID\\<clsid>\\Verb\\3 = <verb3>,<verb3opt>"),
/* 024 */ _T("CLSID\\<clsid>\\Verb\\4 = <verb4>,<verb4opt>"),
/* 025 */ _T("CLSID\\<clsid>\\Verb\\5 = <verb5>,<verb5opt>"),
/* 026 */ _T("CLSID\\<clsid>\\Verb\\6 = <verb6>,<verb6opt>"),
/* 027 */ _T("CLSID\\<clsid>\\Verb\\7 = <verb7>,<verb7opt>"),
 
/* 030 */ _T("CLSID\\<clsid>\\DataFormats\\GetSet\\0 = <format0>"),
/* 031 */ _T("CLSID\\<clsid>\\DataFormats\\GetSet\\1 = <format1>"),
/* 032 */ _T("CLSID\\<clsid>\\DataFormats\\GetSet\\2 = <format2>"),
/* 033 */ _T("CLSID\\<clsid>\\DataFormats\\GetSet\\3 = <format3>"),
/* 034 */ _T("CLSID\\<clsid>\\DataFormats\\GetSet\\4 = <format4>"),
/* 035 */ _T("CLSID\\<clsid>\\DataFormats\\GetSet\\5 = <format5>"),
/* 036 */ _T("CLSID\\<clsid>\\DataFormats\\GetSet\\6 = <format6>"),
/* 037 */ _T("CLSID\\<clsid>\\DataFormats\\GetSet\\7 = <format7>"),
 
/* 040 */ _T("CLSID\\<clsid>\\MiscStatus = <aspectall>"),
/* 041 */ _T("CLSID\\<clsid>\\MiscStatus\\1 = <aspectcontent>"),
/* 042 */ _T("CLSID\\<clsid>\\MiscStatus\\2 = <aspectthumbnail>"),
/* 043 */ _T("CLSID\\<clsid>\\MiscStatus\\4 = <aspecticon>"),
/* 044 */ _T("CLSID\\<clsid>\\MiscStatus\\8 = <aspectdocprint>"),
/* 045 */ _T("CLSID\\<clsid>\\AuxUserType\\2 = <menuname>"),
/* 046 */ _T("CLSID\\<clsid>\\AuxUserType\\3 = <appname>"),
/* 047 */ _T("CLSID\\<clsid>\\Insertable"),
 
/* 050 */ _T("<permid> = <permname>"),
/* 051 */ _T("<permid>\\CLSID = <clsid>"),
/* 052 */ _T("<permid>\\CurVer = <progid>"),
/* 053 */ _T("CLSID\\<clsid>\\VersionIndependentProgID = <permid>"),
 
/* 054 */ _T("CLSID\\<clsid>\\Version = <version>"),
/* 055 */ _T("CLSID\\<clsid>\\DataFormats\\DefaultFile = <filefmt>"),
/* 056 */ _T("CLSID\\<clsid>\\Ole1Class = <progid>"),        /// is this really needed?
/* 057 */ _T(".<extension> = <progid>"),
 
/* 060 */ _T("<progid>\\Shell\\Print\\Command = <path> \"%1\""),
/* 061 */ _T("<progid>\\Shell\\Open\\Command = <path> \"%1\""),
/* 062 */ _T("<progid>\\protocol\\StdFileEditing\\server = <debugger> <path><extraopt>"),
/* 063 */ _T("<progid>\\Insertable"),
 
// Following entries are specific to controls
//
 
/* 064 */ _T("CLSID\\<clsid>\\Control"),
/* 065 */ _T("CLSID\\<clsid>\\ToolBoxBitmap32 = <path>,<toolbmpindex>"),
          0,
};
 
//
/// Registration parameter table, ordering is arbitrary, parameters lowercase
//
static const TRegParamList::TEntry OcRegParams[] = {
  {_T("clsid"),             0, _T("")               },// GUID standard string form
  {_T("progid"),            0, _T("\001\002\003\005\006\007")},// A unique name
  {_T("insertable"),        0, _T("\046\047\062\063")},// Defined to publish server
  {_T("control"),           0, _T("\064\065")       },// Defined to publish control
  {_T("usage"),  ocrSingleUse, _T("")               },// Class factory registration
  {_T("description"),       0, _T("")               },// Human readable, 40 chars max
  {_T("handler"), _T("ole32.dll"), _T("\005")        },// Inproc handler
  {_T("serverctx"),         0, _T("\001")           },// "Local"(EXE) or "Inproc"(DLL)
  {_T("path"),              0, _T("")               },// OC defaults to load path
  {_T("cmdline"),      _T(""), _T("")               },// /Automation if app class
  {_T("debugger"),     _T(""), _T("")               },// Debugger to invoke server
  {_T("permid"),            0, _T("\050\051\053")   },// Version independent clsid
  {_T("permname"),          0, _T("\052")           },// Version independent progid
  {_T("iconindex"),   _T("0"), _T("\004")           },// Zero-based resource icon
  {_T("toolbmpindex"),_T("1"), _T("\065")           },// Index of resource bitmap for palette
  {_T("menuname"),     _T(""), _T("\045")           },// 15 characters maximum
  {_T("appname"),           0, _T("")               },// AppName, AuxUserType/3
  {_T("verb0"),             0, _T("\010\020")       },// Name of primary verb
  {_T("verb1"),             0, _T("\011\021")       },
  {_T("verb2"),             0, _T("\012\022")       },
  {_T("verb3"),             0, _T("\013\023")       },
  {_T("verb4"),             0, _T("\014\024")       },
  {_T("verb5"),             0, _T("\015\025")       },
  {_T("verb6"),             0, _T("\016\026")       },
  {_T("verb7"),             0, _T("\017\027")       },
  {_T("verb8"),             0, _T("\018\028")       },
  {_T("verb0opt"),  _T("0,2"), _T("\020")           },// From REGVERBOPT macro
  {_T("verb1opt"),  _T("0,2"), _T("\021")           },
  {_T("verb2opt"),  _T("0,2"), _T("\022")           },
  {_T("verb3opt"),  _T("0,2"), _T("\023")           },
  {_T("verb4opt"),  _T("0,2"), _T("\024")           },
  {_T("verb5opt"),  _T("0,2"), _T("\025")           },
  {_T("verb6opt"),  _T("0,2"), _T("\026")           },
  {_T("verb7opt"),  _T("0,2"), _T("\027")           },
  {_T("verb8opt"),  _T("0,2"), _T("\028")           },
  {_T("format0"),           0, _T("\030")           },// From REGFORMAT macro
  {_T("format1"),           0, _T("\031")           },
  {_T("format2"),           0, _T("\032")           },
  {_T("format3"),           0, _T("\033")           },
  {_T("format4"),           0, _T("\034")           },
  {_T("format5"),           0, _T("\035")           },
  {_T("format6"),           0, _T("\036")           },
  {_T("format7"),           0, _T("\037")           },
  {_T("format8"),           0, _T("\038")           },
  {_T("filefmt"),           0, _T("\055")           },// Default file format name
  {_T("aspectall"),   _T("0"), _T("\040")           },// Option flags for all aspects
  {_T("aspectcontent"),     0, _T("\041")           },// Option flags for content view
  {_T("aspectthumbnail"),   0, _T("\042")           },// Option flags thumbnail view
  {_T("aspecticon"),        0, _T("\043")           },// Option flags for icon view
  {_T("aspectdocprint"),    0, _T("\044")           },// Option flags docprint view
  {_T("extension"),         0, _T("\057\060\061")   },// Extension for shell loading
  {_T("version"),           0, _T("\054")           },// App/typelib version string
  {_T("helpdir"),           0, _T("")               },// Help directory for typehelp
  {_T("typehelp"),          0, _T("")               },// Help file for type library
  {_T("language"),          0, _T("")               },// Set internally from func arg
  {_T("docflags"),    _T("0"), _T("")               },
  {_T("directory"),         0, _T("")               },
  {_T("docfilter"),         0, _T("")               },
  {_T("debugclsid"),        0, _T("")/*INTERNAL GEN*/},// Internal,NOT USER SPECIFIED
  {_T("extraopt"),     _T(""), _T("")/*INTERNAL USE*/},// Cmdline debug/non-debug flag
  {_T("debugprogid"),       0, _T("")               },// Define to force debug reg
  {_T("debugdesc"),         0, _T("")               },// Different string for debug
  {0,                       0,    0                 },// End
};
 
//
/// Generate OLE registration file image to an output stream
///
/// Process a given regInfo table to produce an ascii registration list out to
/// an ostream. Arguments are:
/// \param regInfo  - main registration list to work from
/// \param  module   - hinstance of program module for 'path' & 'serverctx' entries
/// \param  out      - output stream to receive reg entry lines
/// \param  lang     - language id for 'language' entry & string translation
/// \param  filter   - optional template restricting filter
/// \param  defaults - optional reg entries processed before main list
/// \param  overrides- optional reg entries processed after main list
//
long OcRegisterClass(TRegList& regInfo, TModule* module, tostream& out,
                     TLangId lang, LPCTSTR filter, TRegItem* defaults,
                     TRegItem* overrides)
{
  // Use OCF global registration templates & parameters
  //
  TRegSymbolTable symbolTable(TRegKey::GetClassesRoot(), OcRegTemplates, OcRegParams);
 
  // Initialize the symbol table
  //
  symbolTable.Init(filter);
 
  // Check for language defaulted to system or user configuration &
  // assign language parameter based on TLocaleString's setting
  //
  if (lang == LangSysDefault)
    lang = TLocaleString::SystemDefaultLangId;
  else if (lang == LangUserDefault)
    lang = TLocaleString::UserDefaultLangId;
 
  int langIdx = symbolTable.Params.Find(_T("language"));
  _TCHAR langBuf[10];
  wsprintf(langBuf, _T("%X"), lang);
  symbolTable.Params.Value(langIdx) = langBuf;
 
  // Assign path parameter initially to module load path of the given HINSTANCE
  //
  const int pathSize = 512;
  TAPointer<_TCHAR> path(new _TCHAR[pathSize]);
  if(!module)
    module = &GetGlobalModule();
  module->GetModuleFileName(path, pathSize);
  symbolTable.Params.Value(symbolTable.Params.Find(_T("path"))) = path;
 
  // Assign server context based on whether it is an EXE or a DLL
  //
  // NOTE: Assumes that this code is linked into server's module
  //
  {
    int svrIdx = symbolTable.Params.Find(_T("serverctx"));
    if (svrIdx >= 0)
    {
      if (::GetModuleHandle(0) == module->GetHandle()) // Check instance handle for 32bit EXE
        symbolTable.Params.Value(svrIdx) = _T("Local");
      else
        symbolTable.Params.Value(svrIdx) = _T("Inproc");
    }
  }
 
  // Build params from the 3 lists provided in this order:
  //
  //  0: defaults list (defaults)
  //  1: user list of parameters and custom keys (regList)
  //  2: and overrides list (overrides)
  //
  symbolTable.UpdateParams(lang, defaults);
  symbolTable.UpdateParams(lang, regInfo.Items);
  if (!defaults) { //SL: fix for progId without description, Jul-2009
  bool hasProgId=false;
  bool hasDescription=false;
  TRegItem* regItem;
  for (regItem = regInfo.Items; regItem->Key != 0 && !hasProgId; regItem++) {
    if (strcmp(regItem->Key, "progid") == 0)
      hasProgId=true;
  }
  for (regItem = regInfo.Items; regItem->Key != 0 && !hasDescription; regItem++) {
    if (strcmp(regItem->Key, "description") == 0)
      hasDescription=true;
  }
//  if (regInfo.Lookup("progid") && !regInfo.Lookup("description"))
  if (hasProgId && !hasDescription)
  {
    TRegItem auxAppReg_list[] = {
      { "description", {_T("OCF default description")}},
      {0,{0}} };
    symbolTable.UpdateParams(lang, auxAppReg_list);
  }
  }
  symbolTable.UpdateParams(lang, overrides);
 
  symbolTable.StreamOut(regInfo.Items, out);
 
  // Decode & return document template flags
  //
  int i = symbolTable.Params.Find(_T("docflags"));
  if (i >= 0)
    return _ttol(symbolTable.Params.Value(i));
  return 0;
}
 
//
/// Unregister application or class from registration database
///
/// These params are the only ones needed to unregister an OLE program or class
//
int OcUnregisterClass(TRegList& regInfo, const TRegItem* overrides)
{
  static const TRegistry::TUnregParams unregParams[] = {
    { _T('.'),_T("extension"),   &TRegKey::GetClassesRoot() },
    {     0,  _T("debugclsid"),  &TRegKey::GetClassesRootClsid() },
    {      0,  _T("debugprogid"), &TRegKey::GetClassesRoot() },
    {      0,  _T("clsid"),       &TRegKey::GetClassesRootClsid() },
    {      0,  _T("progid"),      &TRegKey::GetClassesRoot() },
    {      0,  _T("permid"),      &TRegKey::GetClassesRoot() },
    {      0,      0,              0 },
  };
  return TRegistry::Unregister(regInfo, unregParams, overrides);
}
 
//----------------------------------------------------------------------------
// Separate debugging registration for application and documents
// Overrides non-debug values with values from debug keys
//
 
//
//
//
TRegItem OcRegNoDebug[] = { {"debugger", {_T("")}}, {0,{0}} };
TRegItem OcRegNotDll[]  = { {"cmdline", {_T("")}}, {"debugger", {_T("")}}, {0,{0}} };
 
//
// Filters limit the templates used when setting up debug registration
//
_TCHAR AppDebugFilter[] = _T("\001\002\003\005\006\007");
_TCHAR DocDebugFilter[] = _T("\001\002\003\005\006\007")\
                        _T("\020\021\022\023\024\025\026\027")\
                        _T("\030\031\032\033\034\035\036\037")\
                        _T("\040\041\042\043\044\045\046\047")\
                        _T("\054\055\062\063");
 
//
//
//
struct TDebugRegKey { enum { progid,        clsid,   description,   extraopt};};
const _TCHAR* OcReplaceKeys[] =  { _T("progid"), _T("clsid"), _T("description"), _T("extraopt")};
const _TCHAR* OcDebugKeys[] = {_T("debugprogid"), _T("debugclsid"), _T("debugdesc"), _T("debugopt")};
 
//
/// Walk thru a reginfo list using debug entries to create a parallel non-debug
/// set for alternate, debug registration.
/// Return:
/// -   0 - No debug registration needed / available
/// -   1 - Debug registration using passed classid
/// -  -1 - Debug registration using classid found in reginfo
//
int OcSetupDebugReg(TRegList& regInfo, TRegItem* regDebug, TLangId lang, LPTSTR clsid)
{
  LPCTSTR* oldKey = OcReplaceKeys;
  LPCTSTR* newKey = OcDebugKeys;
 
  // Walk thru the special keys with debug alternates
  //
  int stat = -1;         // Initialize for regInfo-supplied clsid
  for (int i = 0; i < COUNTOF(OcReplaceKeys); i++,oldKey++,newKey++,regDebug++) {
    _USES_CONVERSION;
    LPCTSTR value = regInfo.Lookup(_W2A(*newKey), lang);
 
    // If not value found for a given key, supply a default if possible, else
    // throw an exception.
    //
    if (!value) {
      switch (i) {
        case TDebugRegKey::progid:
          return 0;                   // No debug registration if progid missing
        case TDebugRegKey::extraopt:
          value = _T(" /Debug");      // Default to "/Debug" on command line
          break;
        case TDebugRegKey::clsid:
          if (clsid) {
            value = clsid;
            stat = 1;                 // Flag use of supplied clsid
            break;
          }       // else fall through to throw exception--clsid is required
        case TDebugRegKey::description:
          throw TXRegistry{_T("ocf::OcSetupDebugReg: incomplete debug registration"), *newKey};
      }
    }
    regDebug->Key   = _W2A(*oldKey);       // Write normal key + debug value to
    regDebug->Value = value;           // output reg list
  }
  regDebug->Key = 0;                   // 0-terminate reg list
  return stat;
}
 
 
//----------------------------------------------------------------------------
// TRegistrar - Application registration manager interface class
//
 
//
//
//
TRegistrar* TRegistrar::RegistrarList = 0;
 
//
//
//
TRegistrar::TRegistrar(TRegList& regInfo, TComponentFactory callback,
                       owl::tstring& cmdLine, TModule* module)
:
  AppDesc(*new TAppDescriptor(regInfo, callback, cmdLine, module))
{
  Next = RegistrarList;
  RegistrarList = this;
  TRACEX(OcfRefCount, 1, "TRegistrar() @" << (void*)this);
}
 
//
//
//
TRegistrar::TRegistrar(TAppDescriptor& appDesc)
:
  AppDesc(appDesc)
{
  Next = RegistrarList;
  RegistrarList = this;
}
 
//
//
//
TRegistrar::~TRegistrar()
{
  // Since TRegistrars are destroyed when the module is shutdown
  // we do not need to detach each registrar from the linked list
  //
  delete &AppDesc;
}
 
//
//
//
TRegistrar* TRegistrar::GetNext(TRegistrar* reg)
{
  return reg ? reg->Next : RegistrarList;
}
 
//
//
//
void * TRegistrar::GetFactory(const GUID& clsid, const GUID & iid)
{
  void * retObj = 0;
  if (clsid != AppDesc.AppClassId)
    return 0;
  ((IUnknown&)AppDesc).QueryInterface(iid, &retObj);
  return retObj;   // QueryInterface sets to null if fails
}
 
//
//
//
bool TRegistrar::CanUnload()
{
  return static_cast<bool>(!AppDesc.IsBound());
}
 
//
//
//
int TRegistrar::Run()
{
  if (!IsOptionSet(amExeModule))
    return 0;    // inproc server waits until class factory created and called
  TComponentFactory factory = AppDesc.GetFactory();
  if (!factory)
    return 1;
  if (AppDesc.IsAutomated() && IsOptionSet(amAutomation))
    RegisterAppClass();
  IUnknown* ifc = (factory)(0, GetOptions() | amRun, 0);  // create app and run it
 
  // App is now running its message loop, factory may get called again by OLE
  //
  ifc = (factory)(ifc, GetOptions() | amShutdown, 0);  // EXE finished, destroy it
  if (ifc && !(GetOptions() & amServedApp))
    ifc->Release();  // we own the reference count, else container released it
  return 0;
}
 
//
//
//
void TRegistrar::Shutdown(IUnknown* releasedObj, uint32 options)
{
  if (!AppDesc.GetFactory())
    return;
  releasedObj = AppDesc.GetFactory()(releasedObj, options|amShutdown, 0);
  if (releasedObj)
    releasedObj->Release();
}
 
} // OCF namespace
 
//==============================================================================
 
using namespace ocf;
 
//----------------------------------------------------------------------------
// DLL server entry points
//
 
//
/// Entry point for complete registration management via command line
/// Don't let any exceptions blow back to OLE.
//
#  if defined(BI_COMP_MSC)
STDAPI
#else
STDAPI __declspec(dllexport)
#endif
DllRegisterCommand(LPCTSTR cmdLine)
{
  try {
    bool isDebug = false;
    TRegistrar* registrar = 0;
 
    // Need to set up typelibrary state information in case multiple components
    //
    while ((registrar = TRegistrar::GetNext(registrar)) != 0) {
      owl::tstring cmd(cmdLine);
      registrar->ProcessCmdLine(cmd);
      if (registrar->IsOptionSet(amDebug))
        isDebug = true;
    }
    if (isDebug)
      OWL_BREAK;
    return HR_OK;
  }
  catch (...) {
    return HR_FAIL;
  }
}
 
//
/// OLE 2.0 entry point for obtaining a class factory for a particular CLSID
/// Don't let any exceptions blow back to OLE.
//
STDAPI DllGetClassObject(const GUID& clsid, const GUID& iid, void** retObj)
{
  try {
    TRegistrar* registrar = 0;
    while ((registrar = TRegistrar::GetNext(registrar)) != 0) {
      *retObj = registrar->GetFactory(clsid, iid);
      if (*retObj)
        return HR_OK;
    }
    return HR_FAIL;
  }
  catch (...) {
    return HR_FAIL;
  }
}
 
//
/// OLE 2.0 entry point for checking if DLL has no clients and can be unloaded
//
STDAPI DllCanUnloadNow()
{
  TRegistrar* registrar = 0;
  while ((registrar = TRegistrar::GetNext(registrar)) != 0) {
    if (!registrar->CanUnload()) {
      TRACEX(OcfDll, 1, "DllCanUnloadNow returning HR_FALSE");
      return HR_FALSE;
    }
  }
  TRACEX(OcfDll, 1, "DllCanUnloadNow returning HR_OK");
  return HR_OK;
}
 
//
/// OLE 2.0 entry point for registering DLL, no locale info passed
//
STDAPI DllRegisterServer()
{
  return DllRegisterCommand(_T("/RegServer"));
}
 
//
/// OLE 2.0 entry point for unregistering DLL
//
STDAPI DllUnregisterServer()
{
  return DllRegisterCommand(_T("/UnregServer"));
}
 
#if defined(BI_COMP_MSC)
extern "C" BOOL WINAPI RawDllMain(HINSTANCE, DWORD dwReason, LPVOID);
extern "C" BOOL (WINAPI* _pRawDllMain)(HINSTANCE, DWORD, LPVOID) = &RawDllMain;
 
//Jogy - this is not correct!!
#if !defined(OWL_DLLNAME)
#  if defined (_UNICODE)
#     if defined(__TRACE) || defined(__WARN)
#     define OWL_DLLNAME "owl620vud.dll"
#     else
#     define OWL_DLLNAME "owl620vu.dll"
#     endif
#  else
#  if defined(__TRACE) || defined(__WARN)
#    define OWL_DLLNAME "owl620vd.dll"
#  else
#    define OWL_DLLNAME "owl620v.dll"
#  endif
#endif
#endif
 
extern "C"
BOOL WINAPI RawDllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID)
{
  if (dwReason == DLL_PROCESS_ATTACH){
    // Prevent the OWL DLL from being unloaded prematurely
    ::LoadLibraryA(OWL_DLLNAME);
  }
  else if (dwReason == DLL_PROCESS_DETACH){
    // Now it's OK for the OWL DLLs to be unloaded (see LoadLibrary above)
    ::FreeLibrary(GetModuleHandleA(OWL_DLLNAME));
  }
  return TRUE;    // ok
}
 
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, uint32 reason, LPVOID)
#else
int WINAPI DllEntryPoint(HINSTANCE hInstance, uint32 reason, LPVOID)
#endif
{
  //TRACEX(OwlMain, 0, "DllEntryPoint(" << hInstance << ", " << reason << ", " <<
  //       ") called");
 
  switch (reason) {
    case DLL_PROCESS_ATTACH:
 
      // If you provide your own version of DLL EntryPoint, make sure
      // you call OwlInitUserDLL to allow OWL to initialize the global module.
      // Second parameter - command line, if it = 0 std::string will crash //Y.B.
      return OWLInitUserDLL(hInstance, _T("")) ? 1 : 0;
  }
  return 1;
}
 
 
 

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