/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * $Id: Win32PlatformUtils.cpp 568078 2007-08-21 11:43:25Z amassari $
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/RuntimeException.hpp>
#include <xercesc/util/XMemory.hpp>
#include <xercesc/util/XMLHolder.hpp>
#include <xercesc/util/XMLExceptMsgs.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/XMLUni.hpp>
#include <xercesc/util/PanicHandler.hpp>
#include <xercesc/util/OutOfMemoryException.hpp>

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

//
//  These control which transcoding service is used by the Win32 version.
//  They allow this to be controlled from the build process by just defining
//  one of these values.
//
#if defined (XML_USE_ICU_TRANSCODER)
    #include <xercesc/util/Transcoders/ICU/ICUTransService.hpp>
#elif defined (XML_USE_WIN32_TRANSCODER)
    #include <xercesc/util/Transcoders/Win32/Win32TransService.hpp>
#elif defined (XML_USE_CYGWIN_TRANSCODER)
    #include <xercesc/util/Transcoders/Cygwin/CygwinTransService.hpp>
#else
    #error A transcoding service must be chosen
#endif

//
//  These control which message loading service is used by the Win32 version.
//  They allow this to be controlled from the build process by just defining
//  one of these values.
//
#if defined (XML_USE_INMEM_MESSAGELOADER)
    #include <xercesc/util/MsgLoaders/InMemory/InMemMsgLoader.hpp>
#elif defined (XML_USE_WIN32_MSGLOADER)
    #include <xercesc/util/MsgLoaders/Win32/Win32MsgLoader.hpp>
#elif defined(XML_USE_ICU_MESSAGELOADER)
    #include <xercesc/util/MsgLoaders/ICU/ICUMsgLoader.hpp>
#else
    #error A message loading service must be chosen
#endif

//
//  These control which network access service is used by the Win32 version.
//  They allow this to be controlled from the build process by just defining
//  one of these values.
//
#if defined (XML_USE_NETACCESSOR_LIBWWW)
    #include <xercesc/util/NetAccessors/libWWW/LibWWWNetAccessor.hpp>
#elif defined (XML_USE_NETACCESSOR_WINSOCK)
    #include <xercesc/util/NetAccessors/WinSock/WinSockNetAccessor.hpp>
#endif

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  Local data
//
//  gOnNT
//      We figure out during init if we are on NT or not. If we are, then
//      we can avoid a lot of transcoding in our system services stuff.
// ---------------------------------------------------------------------------
static bool     gOnNT;


// ---------------------------------------------------------------------------
//  XMLPlatformUtils: The panic method
// ---------------------------------------------------------------------------
void XMLPlatformUtils::panic(const PanicHandler::PanicReasons reason)
{
    fgUserPanicHandler? fgUserPanicHandler->panic(reason) : fgDefaultPanicHandler->panic(reason);	
}



// ---------------------------------------------------------------------------
//  XMLPlatformUtils: File Methods
// ---------------------------------------------------------------------------

//
//  Functions to look for Unicode forward and back slashes.
//  This operation is complicated by the fact that some Japanese and Korean
//    encodings use the same encoding for both '\' and their currency symbol
//    (Yen or Won).  In these encodings, which is meant is context dependent.
//    Unicode converters choose the currency symbols.  But in the context
//    of a Windows file name, '\' is generally what was intended.
//
//    So we make a leap of faith, and assume that if we get a Yen or Won
//    here, in the context of a file name, that it originated in one of
//    these encodings, and is really supposed to be a '\'.
//
static bool isBackSlash(XMLCh c) {
    return c == chBackSlash ||
           c == chYenSign   ||
           c == chWonSign;
}

unsigned int XMLPlatformUtils::curFilePos(FileHandle theFile
                                          , MemoryManager* const manager)
{
    // Get the current position
    const unsigned int curPos = ::SetFilePointer(theFile, 0, 0, FILE_CURRENT);
    if (curPos == 0xFFFFFFFF)
        ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetCurPos, manager);

    return curPos;
}

void XMLPlatformUtils::closeFile(FileHandle theFile
                                 , MemoryManager* const manager)
{
    if (!::CloseHandle(theFile))
        ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotCloseFile, manager);
}

unsigned int XMLPlatformUtils::fileSize(FileHandle theFile
                                        , MemoryManager* const manager)
{
    // Get the current position
    const unsigned int curPos = ::SetFilePointer(theFile, 0, 0, FILE_CURRENT);
    if (curPos == 0xFFFFFFFF)
        ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetCurPos, manager);

    // Seek to the end and save that value for return
    const unsigned int retVal = ::SetFilePointer(theFile, 0, 0, FILE_END);
    if (retVal == 0xFFFFFFFF)
        ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToEnd, manager);

    // And put the pointer back
    if (::SetFilePointer(theFile, curPos, 0, FILE_BEGIN) == 0xFFFFFFFF)
        ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotSeekToPos, manager);

    return retVal;
}

FileHandle XMLPlatformUtils::openFile(const char* const fileName
                                      , MemoryManager* const /*manager*/)
{
    FileHandle retVal = ::CreateFileA
    (
        fileName
        , GENERIC_READ
        , FILE_SHARE_READ
        , 0
        , OPEN_EXISTING
        , FILE_FLAG_SEQUENTIAL_SCAN
        , 0
    );

    if (retVal == INVALID_HANDLE_VALUE)
        return 0;

    return retVal;
}

FileHandle XMLPlatformUtils::openFile(const XMLCh* const fileName
                                      , MemoryManager* const manager)
{
    // Watch for obvious wierdness
    if (!fileName)
        return 0;

    //
    //  We have to play a little trick here. If its /x:.....
    //  style fully qualified path, we have to toss the leading /
    //  character.
    //
    const XMLCh* nameToOpen = fileName;
    if (*fileName == chForwardSlash)
    {
        if (XMLString::stringLen(fileName) > 3)
        {
            if (*(fileName + 2) == chColon)
            {
                const XMLCh chDrive = *(fileName + 1);
                if (((chDrive >= chLatin_A) && (chDrive <= chLatin_Z))
                ||  ((chDrive >= chLatin_a) && (chDrive <= chLatin_z)))
                {
                    nameToOpen = fileName + 1;
                }
            }

            // Similarly for UNC paths
            if ( *(fileName + 1) == *(fileName + 2) &&
                 (*(fileName + 1) == chForwardSlash ||
                  *(fileName + 1) == chBackSlash) )
            {
                nameToOpen = fileName + 1;
            }
        }
    }

    //  Ok, this might look stupid but its a semi-expedient way to deal
    //  with a thorny problem. Shift-JIS and some other Asian encodings
    //  are fundamentally broken and map both the backslash and the Yen
    //  sign to the same code point. Transcoders have to pick one or the
    //  other to map '\' to Unicode and tend to choose the Yen sign.
    //
    //  Unicode Yen or Won signs as directory separators will fail.
    //
    //  So, we will check this path name for Yen or won signs and, if they are
    //  there, we'll replace them with slashes.
    //
    //  A further twist:  we replace Yen and Won with forward slashes rather
    //   than back slashes.  Either form of slash will work as a directory
    //   separator.  On Win 95 and 98, though, Unicode back-slashes may
    //   fail to transode back to 8-bit 0x5C with some Unicode converters
    //   to  some of the problematic code pages.  Forward slashes always
    //   transcode correctly back to 8 bit char * form.
    //
    XMLCh *tmpUName = 0;

    const XMLCh* srcPtr = nameToOpen;
    while (*srcPtr)
    {
        if (*srcPtr == chYenSign ||
            *srcPtr == chWonSign)
            break;
        srcPtr++;
    }

    //
    //  If we found a yen, then we have to create a temp file name. Else
    //  go with the file name as is and save the overhead.
    //
    if (*srcPtr)
    {
        tmpUName = XMLString::replicate(nameToOpen, manager);

        XMLCh* tmpPtr = tmpUName;
        while (*tmpPtr)
        {
            if (*tmpPtr == chYenSign ||
                *tmpPtr == chWonSign)
                *tmpPtr = chForwardSlash;
            tmpPtr++;
        }
        nameToOpen = tmpUName;
    }
    FileHandle retVal = 0;
    if (gOnNT)
    {
        retVal = ::CreateFileW
            (
            (LPCWSTR) nameToOpen
            , GENERIC_READ
            , FILE_SHARE_READ
            , 0
            , OPEN_EXISTING
            , FILE_FLAG_SEQUENTIAL_SCAN
            , 0
            );
    }
    else
    {
        //
        //  We are Win 95 / 98.  Take the Unicode file name back to (char *)
        //    so that we can open it.
        //
        char* tmpName = XMLString::transcode(nameToOpen, manager);
        retVal = ::CreateFileA
            (
            tmpName
            , GENERIC_READ
            , FILE_SHARE_READ
            , 0
            , OPEN_EXISTING
            , FILE_FLAG_SEQUENTIAL_SCAN
            , 0
            );
        manager->deallocate(tmpName);//delete [] tmpName;
    }

    if (tmpUName)
        manager->deallocate(tmpUName);//delete [] tmpUName;

    if (retVal == INVALID_HANDLE_VALUE)
        return 0;

    return retVal;
}

FileHandle XMLPlatformUtils::openFileToWrite(const char* const fileName
                                             , MemoryManager* const /*manager*/)
{
    FileHandle retVal = ::CreateFileA
    (
        fileName
        , GENERIC_WRITE
        , 0              // no shared write
        , 0
        , CREATE_ALWAYS
        , FILE_ATTRIBUTE_NORMAL
        , 0
    );

    if (retVal == INVALID_HANDLE_VALUE)
        return 0;

    return retVal;
}

FileHandle XMLPlatformUtils::openFileToWrite(const XMLCh* const fileName
                                             , MemoryManager* const manager)
{
    // Watch for obvious wierdness
    if (!fileName)
        return 0;

    //  Ok, this might look stupid but its a semi-expedient way to deal
    //  with a thorny problem. Shift-JIS and some other Asian encodings
    //  are fundamentally broken and map both the backslash and the Yen
    //  sign to the same code point. Transcoders have to pick one or the
    //  other to map '\' to Unicode and tend to choose the Yen sign.
    //
    //  Unicode Yen or Won signs as directory separators will fail.
    //
    //  So, we will check this path name for Yen or won signs and, if they are
    //  there, we'll replace them with slashes.
    //
    //  A further twist:  we replace Yen and Won with forward slashes rather
    //   than back slashes.  Either form of slash will work as a directory
    //   separator.  On Win 95 and 98, though, Unicode back-slashes may
    //   fail to transode back to 8-bit 0x5C with some Unicode converters
    //   to  some of the problematic code pages.  Forward slashes always
    //   transcode correctly back to 8 bit char * form.
    //
    XMLCh *tmpUName = 0;
    const XMLCh *nameToOpen = fileName;

    const XMLCh* srcPtr = fileName;
    while (*srcPtr)
    {
        if (*srcPtr == chYenSign ||
            *srcPtr == chWonSign)
            break;
        srcPtr++;
    }

    //
    //  If we found a yen, then we have to create a temp file name. Else
    //  go with the file name as is and save the overhead.
    //
    if (*srcPtr)
    {
        tmpUName = XMLString::replicate(fileName, manager);

        XMLCh* tmpPtr = tmpUName;
        while (*tmpPtr)
        {
            if (*tmpPtr == chYenSign ||
                *tmpPtr == chWonSign)
                *tmpPtr = chForwardSlash;
            tmpPtr++;
        }
        nameToOpen = tmpUName;
    }
    FileHandle retVal = 0;
    if (gOnNT)
    {
        retVal = ::CreateFileW
            (
            (LPCWSTR) nameToOpen
            , GENERIC_WRITE
            , 0              // no shared write
            , 0
            , CREATE_ALWAYS
            , FILE_ATTRIBUTE_NORMAL
            , 0
            );
    }
    else
    {
        //
        //  We are Win 95 / 98.  Take the Unicode file name back to (char *)
        //    so that we can open it.
        //
        char* tmpName = XMLString::transcode(nameToOpen, manager);
        retVal = ::CreateFileA
            (
            tmpName
            , GENERIC_WRITE
            , 0              // no shared write
            , 0
            , CREATE_ALWAYS
            , FILE_ATTRIBUTE_NORMAL
            , 0
            );
        manager->deallocate(tmpName);//delete [] tmpName;
    }

    if (tmpUName)
        manager->deallocate(tmpUName);//delete [] tmpUName;

    if (retVal == INVALID_HANDLE_VALUE)
        return 0;

    return retVal;
}

FileHandle XMLPlatformUtils::openStdInHandle(MemoryManager* const manager)
{
    //
    //  Get the standard input handle. Duplicate it and return that copy
    //  since the outside world cannot tell the difference and will shut
    //  down this handle when its done with it. If we gave out the orignal,
    //  shutting it would prevent any further output.
    //
    HANDLE stdInOrg = ::GetStdHandle(STD_INPUT_HANDLE);
    if (stdInOrg == INVALID_HANDLE_VALUE) {
        XMLCh stdinStr[] = {chLatin_s, chLatin_t, chLatin_d, chLatin_i, chLatin_n, chNull};
        ThrowXMLwithMemMgr1(XMLPlatformUtilsException, XMLExcepts::File_CouldNotOpenFile, stdinStr, manager);
    }

    HANDLE retHandle;
    if (!::DuplicateHandle
    (
        ::GetCurrentProcess()
        , stdInOrg
        , ::GetCurrentProcess()
        , &retHandle
        , 0
        , FALSE
        , DUPLICATE_SAME_ACCESS))
    {
        ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotDupHandle, manager);
    }
    return retHandle;
}


unsigned int
XMLPlatformUtils::readFileBuffer(       FileHandle      theFile
                                , const unsigned int    toRead
                                ,       XMLByte* const  toFill
                                , MemoryManager* const  manager)
{
    unsigned long bytesRead = 0;
    if (!::ReadFile(theFile, toFill, toRead, &bytesRead, 0))
    {
        //
        //  Check specially for a broken pipe error. If we get this, it just
        //  means no more data from the pipe, so return zero.
        //
        if (::GetLastError() != ERROR_BROKEN_PIPE)
            ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotReadFromFile, manager);
    }
    return (unsigned int)bytesRead;
}

void
XMLPlatformUtils::writeBufferToFile( FileHandle     const  theFile
                                   , long                  toWrite
                                   , const XMLByte* const  toFlush
                                   , MemoryManager* const  manager)
{
    if (!theFile        ||
        (toWrite <= 0 ) ||
        !toFlush         )
        return;

    const XMLByte* tmpFlush = (const XMLByte*) toFlush;
    unsigned long  bytesWritten = 0;

    while (true)
    {
        if (!::WriteFile(theFile, tmpFlush, toWrite, &bytesWritten, 0))
            ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotWriteToFile, manager);

        if (bytesWritten < (unsigned long) toWrite) //incomplete write
        {
            tmpFlush+=bytesWritten;
            toWrite-=bytesWritten;
            bytesWritten=0;
        }
        else
            return;
    }
}

void XMLPlatformUtils::resetFile(FileHandle theFile
                                 , MemoryManager* const manager)
{
    // Seek to the start of the file
    if (::SetFilePointer(theFile, 0, 0, FILE_BEGIN) == 0xFFFFFFFF)
        ThrowXMLwithMemMgr(XMLPlatformUtilsException, XMLExcepts::File_CouldNotResetFile, manager);

}


// ---------------------------------------------------------------------------
//  XMLPlatformUtils: File system methods
// ---------------------------------------------------------------------------
XMLCh* XMLPlatformUtils::getFullPath(const XMLCh* const srcPath,
                                     MemoryManager* const manager)
{
    //
    //  If we are on NT, then use wide character APIs, else use ASCII APIs.
    //  We have to do it manually since we are only built in ASCII mode from
    //  the standpoint of the APIs.
    //
    if (gOnNT)
    {
        // Use a local buffer that is big enough for the largest legal path
        const unsigned int bufSize = 1024;
        XMLCh tmpPath[bufSize + 1];

        XMLCh* namePart = 0;
        if (!::GetFullPathNameW((LPCWSTR)srcPath, bufSize, (LPWSTR)tmpPath, (LPWSTR*)&namePart))
            return 0;

        // Return a copy of the path
        return XMLString::replicate(tmpPath, manager);
    }
     else
    {
        // Transcode the incoming string
        char* tmpSrcPath = XMLString::transcode(srcPath, fgMemoryManager);
        ArrayJanitor<char> janSrcPath(tmpSrcPath, fgMemoryManager);

        // Use a local buffer that is big enough for the largest legal path
        const unsigned int bufSize = 511;
        char tmpPath[511 + 1];

        char* namePart = 0;
        if (!::GetFullPathNameA(tmpSrcPath, bufSize, tmpPath, &namePart))
            return 0;

        // Return a transcoded copy of the path
        return XMLString::transcode(tmpPath, manager);
    }
}

bool XMLPlatformUtils::isRelative(const XMLCh* const toCheck
                                  , MemoryManager* const /*manager*/)
{
    // Check for pathological case of empty path
    if (!toCheck[0])
        return false;

    //
    //  If its starts with a drive, then it cannot be relative. Note that
    //  we checked the drive not being empty above, so worst case its one
    //  char long and the check of the 1st char will fail because its really
    //  a null character.
    //
    if (toCheck[1] == chColon)
    {
        if (((toCheck[0] >= chLatin_A) && (toCheck[0] <= chLatin_Z))
        ||  ((toCheck[0] >= chLatin_a) && (toCheck[0] <= chLatin_z)))
        {
            return false;
        }
    }

    //
    //  If it starts with a double slash, then it cannot be relative since
    //  it's a remote file.
    //
    if (isBackSlash(toCheck[0]))
        return false;

    // Else assume its a relative path
    return true;
}

XMLCh* XMLPlatformUtils::getCurrentDirectory(MemoryManager* const manager)
{
    //
    //  If we are on NT, then use wide character APIs, else use ASCII APIs.
    //  We have to do it manually since we are only built in ASCII mode from
    //  the standpoint of the APIs.
    //
    if (gOnNT)
    {
        // Use a local buffer that is big enough for the largest legal path
        const unsigned int bufSize = 1024;
        XMLCh tmpPath[bufSize + 1];

        if (!::GetCurrentDirectoryW(bufSize, (LPWSTR)tmpPath))
            return 0;

        // Return a copy of the path
        return XMLString::replicate(tmpPath, manager);
    }
     else
    {
        // Use a local buffer that is big enough for the largest legal path
        const unsigned int bufSize = 511;
        char tmpPath[511 + 1];

        if (!::GetCurrentDirectoryA(bufSize, tmpPath))
            return 0;

        // Return a transcoded copy of the path
        return XMLString::transcode(tmpPath, manager);
    }
}

inline bool XMLPlatformUtils::isAnySlash(XMLCh c)
{
    return c == chBackSlash    ||
           c == chForwardSlash ||
           c == chYenSign      ||
           c == chWonSign;
}

// ---------------------------------------------------------------------------
//  XMLPlatformUtils: Timing Methods
// ---------------------------------------------------------------------------
unsigned long XMLPlatformUtils::getCurrentMillis()
{
    return (unsigned long)::GetTickCount();
}


typedef XMLHolder<CRITICAL_SECTION>  MutexHolderType;


// ---------------------------------------------------------------------------
//  Mutex methods
// ---------------------------------------------------------------------------
void XMLPlatformUtils::closeMutex(void* const mtxHandle)
{
    MutexHolderType* const  holder = MutexHolderType::castTo(mtxHandle);

    ::DeleteCriticalSection(&holder->fInstance);
    delete holder;
}


void XMLPlatformUtils::lockMutex(void* const mtxHandle)
{
    ::EnterCriticalSection(&MutexHolderType::castTo(mtxHandle)->fInstance);
}


void* XMLPlatformUtils::makeMutex(MemoryManager* manager)
{
    MutexHolderType* const  holder = new (manager) MutexHolderType;

    InitializeCriticalSection(&holder->fInstance);

    return holder;
}


void XMLPlatformUtils::unlockMutex(void* const mtxHandle)
{
    ::LeaveCriticalSection(&MutexHolderType::castTo(mtxHandle)->fInstance);
}


// ---------------------------------------------------------------------------
//  Miscellaneous synchronization methods
// ---------------------------------------------------------------------------
void*
XMLPlatformUtils::compareAndSwap(       void**      toFill
                                , const void* const newValue
                                , const void* const toCompare)
{
#if defined WIN64
    return ::InterlockedCompareExchangePointer(toFill, (void*)newValue, (void*)toCompare);
#else

    //
    //  InterlockedCompareExchange is only supported on Windows 98,
    //  Windows NT 4.0, and newer -- not on Windows 95...
    //  If you are willing to give up Win95 support change this to #if 0
    //  otherwise we are back to using assembler.
    //  (But only if building with compilers that support inline assembler.)
    //
    #if (defined(_MSC_VER) || defined(__BCPLUSPLUS__)) && !defined(XERCES_NO_ASM)

    void*   result;
    __asm
    {
        mov             eax, toCompare;
        mov             ebx, newValue;
        mov             ecx, toFill
        lock cmpxchg    [ecx], ebx;
        mov             result, eax;
    }
    return result;

    #else

    //
    //  Note we have to cast off the constness of some of these because
    //  the system APIs are not C++ aware in all cases.
    //

    return (void*) ::InterlockedCompareExchange((LPLONG)toFill, (LONG)newValue, (LONG)toCompare);

    #endif

#endif

}


// ---------------------------------------------------------------------------
//  Atomic increment and decrement methods
// ---------------------------------------------------------------------------
int XMLPlatformUtils::atomicIncrement(int &location)
{
    return ::InterlockedIncrement(&(long &)location);
}


int XMLPlatformUtils::atomicDecrement(int &location)
{
    return ::InterlockedDecrement(&(long &)location);
}



// ---------------------------------------------------------------------------
//  XMLPlatformUtils: Private Static Methods
// ---------------------------------------------------------------------------

//
//  This method is called by the platform independent part of this class
//  during initialization. We have to create the type of net accessor that
//  we want to use. If none, then just return zero.
//
XMLNetAccessor* XMLPlatformUtils::makeNetAccessor()
{
#if defined (XML_USE_NETACCESSOR_LIBWWW)
    return new (fgMemoryManager) LibWWWNetAccessor();
#elif defined (XML_USE_NETACCESSOR_WINSOCK)
    return new (fgMemoryManager) WinSockNetAccessor();
#else
    return 0;
#endif
}


//
//  This method is called by the platform independent part of this class
//  when client code asks to have one of the supported message sets loaded.
//  In our case, we use the ICU based message loader mechanism.
//
XMLMsgLoader* XMLPlatformUtils::loadAMsgSet(const XMLCh* const msgDomain)
{
    XMLMsgLoader* retVal;
    try
    {
#if defined (XML_USE_INMEM_MESSAGELOADER)
        retVal = new (fgMemoryManager) InMemMsgLoader(msgDomain);
#elif defined (XML_USE_WIN32_MSGLOADER)
        retVal = new (fgMemoryManager) Win32MsgLoader(msgDomain);
#elif defined (XML_USE_ICU_MESSAGELOADER)
        retVal = new (fgMemoryManager) ICUMsgLoader(msgDomain);
#else
        #error You must provide a message loader
        return 0;
#endif
    }
    catch(const OutOfMemoryException&)
    {
        throw;
    }
    catch(...)
    {
        panic(PanicHandler::Panic_CantLoadMsgDomain);
    }
    return retVal;
}


//
//  This method is called very early in the bootstrapping process. This guy
//  must create a transcoding service and return it. It cannot use any string
//  methods, any transcoding services, throw any exceptions, etc... It just
//  makes a transcoding service and returns it, or returns zero on failure.
//
XMLTransService* XMLPlatformUtils::makeTransService()
{
    //
    //  Since we are going to use the ICU service, we have to tell it where
    //  its converter files are. If the ICU_DATA environment variable is set,
    //  then its been told. Otherwise, we tell it our default value relative
    //  to our DLL.
    //
#if defined (XML_USE_ICU_TRANSCODER)
    return new (fgMemoryManager) ICUTransService;
#elif defined (XML_USE_WIN32_TRANSCODER)
    return new (fgMemoryManager) Win32TransService;
#elif defined (XML_USE_CYGWIN_TRANSCODER)
    return new (fgMemoryManager) CygwinTransService;
#else
    #error You must provide a transcoding service implementation
#endif
}


//
//  This method handles the Win32 per-platform basic init functions. The
//  primary jobs here are getting the path to our DLL and to get the
//  stdout and stderr file handles setup.
//

//  Enable this code for memeory leak testing
//#define MEM_LEAK_TESTING

#ifdef MEM_LEAK_TESTING
    #include <crtdbg.h>
#endif

void XMLPlatformUtils::platformInit()
{

#ifdef MEM_LEAK_TESTING
   // Send all reports to STDOUT
   _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
   _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
   _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
   _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
   _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
   _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );

    int tmpDbgFlag;
    tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
    tmpDbgFlag |= _CRTDBG_LEAK_CHECK_DF;
    _CrtSetDbgFlag(tmpDbgFlag);
#endif

    // Figure out if we are on NT and save that flag for later use
    OSVERSIONINFO   OSVer;
    OSVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    ::GetVersionEx(&OSVer);
    gOnNT = (OSVer.dwPlatformId == VER_PLATFORM_WIN32_NT);
}


void XMLPlatformUtils::platformTerm()
{
    // We don't have any temrination requirements for win32 at this time
}

#include <xercesc/util/LogicalPath.c>

XERCES_CPP_NAMESPACE_END
