//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// GENERAL LIBRARY ROUTINES (INITIALIZATION/FINALIZATION, ETC.) EXPORTED FROM "NativeLib.dll":
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// NativeLib DLL (for DotNetHelpers) | C+- (SysRoutine) | Author: Sergei Y.Kitáev
#include "Precompiled.h"
#include "SharedIncludes.h"
#include <HelpersRT.h>
//==================================================================================================
NL_API
BOOL WINAPI NLib_Initialize($CI_TAG, PCWSTR mainModuleName $optional,
                                     const NLInitStruct* initStructurePtr,
                                     PWSTR* pErrorMessagePtr $out ) nl_not_requires_init
{
   $TCI_VERIFY_POINTER_ARG( initStructurePtr );
   $TCI_VERIFY_POINTER_ARG( pErrorMessagePtr );
   const NLInitStruct &ini = *initStructurePtr;
   PWSTR &errorMessagePtr = *pErrorMessagePtr;
   errorMessagePtr = nullptr;
//$FatalError::RaiseInvalidOperation($TCI);

   if ( LIB::is_initialized )
   {
      errorMessagePtr = HelpersRT::DuplicateSZ($TCI, $TEXT(
         L"Attempt of repeatedly initialize “NativeLib.dll”.",
         L"Попытка повторной инициализации “NativeLib.dll”." ));
      return false;
   }

   $RuntimeParameters rtParams;
   rtParams.Prepare($TCI, LIB::dll_name, "", ini.AllowDesktopInteraction ); // LC_ALL=""
   rtParams.ModuleParameters.MainModuleName = mainModuleName;
   rtParams.IsNativeThreadStartForbiddenVCRT = true;

   $ExitCodesRT &ex = rtParams.ExitCodes;
   ex.Successful  = ini.SuccessfulExitCode;
   ex.Failure     = ini.FailureExitCode;
   ex.Breakdown   = ini.BreakdownExitCode;

   $LOCK( LIB::initialization_cs );
   $DynText errorMessage;
   if ( !$RT::Initialize($TCI, rtParams, errorMessage ) )
   {
      errorMessagePtr = HelpersRT::DuplicateSZ($TCI, errorMessage.T($) );
      return false;
   }

   return DLL::PrepareThread($TCI, -1, pErrorMessagePtr ) ?
      LIB::is_initialized = true :
      false;
}

//--------------------------------------------------------------------------------------------------
NL_API
BOOL WINAPI NLib_IsInitialized() nl_not_requires_init
{
   return LIB::is_initialized;
}

//--------------------------------------------------------------------------------------------------
NL_API
HANDLE WINAPI NLib_GetLastError($CI_TAG)
{
   NL_API_ENTRY_VERIFY_0();
   auto pointer = $tls::GetPointer<NLError>($, &LIB::error_pointer_tls );
   $VERIFY_POINTER( pointer );
   return pointer;
}

//--------------------------------------------------------------------------------------------------
NL_API
VOID WINAPI NLib_MemFree(PVOID memoryBlock $optional) nl_not_requires_init
{
   $Memory::Free( memoryBlock );
}

//==================================================================================================
