| /* |
| * The Apache Software License, Version 1.1 |
| * |
| * Copyright (c) 1999 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, |
| * if any, must include the following acknowledgment: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowledgment may appear in the software itself, |
| * if and wherever such third-party acknowledgments normally appear. |
| * |
| * 4. The names "Xerces" and "Apache Software Foundation" must |
| * not be used to endorse or promote products derived from this |
| * software without prior written permission. For written |
| * permission, please contact apache\@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache", |
| * nor may "Apache" appear in their name, without prior written |
| * permission of the Apache Software Foundation. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation, and was |
| * originally based on software copyright (c) 1999, International |
| * Business Machines, Inc., http://www.ibm.com . For more information |
| * on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| */ |
| |
| /** |
| * $Log$ |
| * Revision 1.1 1999/11/09 01:06:21 twl |
| * Initial revision |
| * |
| * Revision 1.4 1999/11/08 20:45:33 rahul |
| * Swat for adding in Product name and CVS comment log variable. |
| * |
| */ |
| |
| // --------------------------------------------------------------------------- |
| // Includes |
| // --------------------------------------------------------------------------- |
| #include <util/Janitor.hpp> |
| #include <util/PlatformUtils.hpp> |
| #include <util/RuntimeException.hpp> |
| #include <util/XMLExceptMsgs.hpp> |
| #include <util/XMLString.hpp> |
| #include <util/XMLUni.hpp> |
| #include <windows.h> |
| |
| #if defined (XML_USE_ICU_TRANSCODER) |
| #include <util/Transcoders/ICU/ICUTransService.hpp> |
| #elif defined (XML_USE_WIN32_TRANSCODER) |
| #include <util/Transcoders/Win32/Win32TransService.hpp> |
| #else |
| #error A transcoding service must be chosen |
| #endif |
| |
| #if defined (XML_USE_INMEMORY_MSGLOADER) |
| #include <util/MsgLoaders/InMemory/InMemMsgLoader.hpp> |
| #elif defined (XML_USE_WIN32_MSGLOADER) |
| #include <util/MsgLoaders/Win32/Win32MsgLoader.hpp> |
| #else |
| #error A message loading service must be chosen |
| #endif |
| |
| |
| // --------------------------------------------------------------------------- |
| // 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. |
| // |
| // gStdErr |
| // gStdOut |
| // The file handles for standard error and standard out. We set these |
| // up during init. Note that they can be zero if there are no std |
| // handles, |
| // |
| // gStdErrRedir |
| // gStdOutRedir |
| // These flags are set to indicate whether their respective output |
| // handles are redirected. If they are not, then we can use console |
| // APIs on NT to write Unicode straight to the output. Otherwise we have |
| // to use file APIs, and we transcode it. |
| // --------------------------------------------------------------------------- |
| static bool gOnNT; |
| static HANDLE gStdErr; |
| static bool gStdErrRedir; |
| static HANDLE gStdOut; |
| static bool gStdOutRedir; |
| |
| |
| // --------------------------------------------------------------------------- |
| // Local methods |
| // --------------------------------------------------------------------------- |
| static void WriteCharStrStdErr(const char* const toWrite) |
| { |
| // We always just use the file APIs for these |
| DWORD written; |
| if (!::WriteFile |
| ( |
| gStdErr |
| , toWrite |
| , strlen(toWrite) |
| , &written |
| , 0)) |
| { |
| // |
| // If if fails due to an invalid handle, then just assume that our |
| // handles were disconnected and zero it out. This will prevent us |
| // from getting called again. |
| // |
| if (::GetLastError() == ERROR_INVALID_HANDLE) |
| gStdErr = 0; |
| else |
| ThrowXML(XMLPlatformUtilsException, XML4CExcepts::Strm_StdErrWriteFailure); |
| } |
| } |
| |
| |
| static void WriteCharStrStdOut(const char* const toWrite) |
| { |
| // We always just use the file APIs for these |
| DWORD written; |
| if (!::WriteFile |
| ( |
| gStdOut |
| , toWrite |
| , strlen(toWrite) |
| , &written |
| , 0)) |
| { |
| // |
| // If if fails due to an invalid handle, then just assume that our |
| // handles were disconnected and zero it out. This will prevent us |
| // from getting called again. |
| // |
| if (::GetLastError() == ERROR_INVALID_HANDLE) |
| gStdOut = 0; |
| else |
| ThrowXML(XMLPlatformUtilsException, XML4CExcepts::Strm_StdOutWriteFailure); |
| } |
| } |
| |
| |
| static void WriteUStrStdErr(const XMLCh* const toWrite) |
| { |
| // |
| // If we are on NT and the handle is not redirected, then we can use |
| // the console API directly to send out Unicode. Otherwise we have to |
| // use the file APIs and transcode. |
| // |
| DWORD written; |
| if (gOnNT && !gStdErrRedir) |
| { |
| if (!::WriteConsoleW |
| ( |
| gStdErr |
| , toWrite |
| , XMLString::stringLen(toWrite) |
| , &written |
| , 0)) |
| { |
| ThrowXML(XMLPlatformUtilsException, XML4CExcepts::Strm_ConWriteFailure); |
| } |
| return; |
| } |
| |
| // Oh well, got to do it the hard way |
| char* tmpVal = XMLString::transcode(toWrite); |
| ArrayJanitor<char> janTmp(tmpVal); |
| WriteCharStrStdErr(tmpVal); |
| } |
| |
| |
| static void WriteUStrStdOut(const XMLCh* const toWrite) |
| { |
| // |
| // If we are on NT and the handle is not redirected, then we can use |
| // the console API directly to send out Unicode. Otherwise we have to |
| // use the file APIs and transcode. |
| // |
| DWORD written; |
| if (gOnNT && !gStdOutRedir) |
| { |
| if (!::WriteConsoleW |
| ( |
| gStdOut |
| , toWrite |
| , XMLString::stringLen(toWrite) |
| , &written |
| , 0)) |
| { |
| ThrowXML(XMLPlatformUtilsException, XML4CExcepts::Strm_ConWriteFailure); |
| } |
| return; |
| } |
| |
| // Oh well, got to do it the hard way |
| char* tmpVal = XMLString::transcode(toWrite); |
| ArrayJanitor<char> janTmp(tmpVal); |
| WriteCharStrStdOut(tmpVal); |
| } |
| |
| |
| |
| // --------------------------------------------------------------------------- |
| // XMLPlatformUtils: The panic method |
| // --------------------------------------------------------------------------- |
| void XMLPlatformUtils::panic(const PanicReasons reason) |
| { |
| const char* reasonStr = "Uknown reason"; |
| if (reason == Panic_NoTransService) |
| reasonStr = "Could not load a transcoding service"; |
| else if (reason == Panic_NoDefTranscoder) |
| reasonStr = "Could not load a local code page transcoder"; |
| else if (reason == Panic_CantFindLib) |
| reasonStr = "Could not find the XML4C DLL"; |
| else if (reason == Panic_UnknownMsgDomain) |
| reasonStr = "Unknown message domain"; |
| else if (reason == Panic_CantLoadMsgDomain) |
| reasonStr = "Cannot load message domain"; |
| |
| // |
| // We just do a popup and exit. Replace this code to do whatever |
| // you need to do. |
| // |
| MessageBoxA |
| ( |
| 0 |
| , "XML4C Panic Error" |
| , reasonStr |
| , MB_OK | MB_ICONSTOP |
| ); |
| exit(-1); |
| } |
| |
| |
| |
| // --------------------------------------------------------------------------- |
| // XMLPlatformUtils: File Methods |
| // --------------------------------------------------------------------------- |
| unsigned int XMLPlatformUtils::curFilePos(FileHandle theFile) |
| { |
| // Get the current position |
| const unsigned int curPos = ::SetFilePointer(theFile, 0, 0, FILE_CURRENT); |
| if (curPos == 0xFFFFFFFF) |
| ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotGetCurPos); |
| |
| return curPos; |
| } |
| |
| void XMLPlatformUtils::closeFile(FileHandle theFile) |
| { |
| if (!::CloseHandle(theFile)) |
| ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotCloseFile); |
| } |
| |
| unsigned int XMLPlatformUtils::fileSize(const FileHandle theFile) |
| { |
| // Get the current position |
| const unsigned int curPos = ::SetFilePointer(theFile, 0, 0, FILE_CURRENT); |
| if (curPos == 0xFFFFFFFF) |
| ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotGetCurPos); |
| |
| // Seek to the end and save that value for return |
| const unsigned int retVal = ::SetFilePointer(theFile, 0, 0, FILE_END); |
| if (curPos == 0xFFFFFFFF) |
| ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotSeekToEnd); |
| |
| // And put the pointer back |
| if (::SetFilePointer(theFile, curPos, 0, FILE_BEGIN) == 0xFFFFFFFF) |
| ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotSeekToPos); |
| |
| return retVal; |
| } |
| |
| FileHandle XMLPlatformUtils::openFile(const char* const fileName) |
| { |
| 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) |
| { |
| FileHandle retVal = 0; |
| if (gOnNT) |
| { |
| retVal = ::CreateFileW |
| ( |
| fileName |
| , GENERIC_READ |
| , FILE_SHARE_READ |
| , 0 |
| , OPEN_EXISTING |
| , FILE_FLAG_SEQUENTIAL_SCAN |
| , 0 |
| ); |
| } |
| else |
| { |
| char* tmpName = XMLString::transcode(fileName); |
| retVal = ::CreateFileA |
| ( |
| tmpName |
| , GENERIC_READ |
| , FILE_SHARE_READ |
| , 0 |
| , OPEN_EXISTING |
| , FILE_FLAG_SEQUENTIAL_SCAN |
| , 0 |
| ); |
| delete [] tmpName; |
| } |
| |
| if (retVal == INVALID_HANDLE_VALUE) |
| return 0; |
| |
| return retVal; |
| } |
| |
| |
| FileHandle XMLPlatformUtils::openStdInHandle() |
| { |
| // |
| // 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) |
| ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotOpenFile); |
| |
| HANDLE retHandle; |
| if (!::DuplicateHandle |
| ( |
| ::GetCurrentProcess() |
| , stdInOrg |
| , ::GetCurrentProcess() |
| , &retHandle |
| , 0 |
| , FALSE |
| , DUPLICATE_SAME_ACCESS)) |
| { |
| ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotDupHandle); |
| } |
| return retHandle; |
| } |
| |
| |
| unsigned int |
| XMLPlatformUtils::readFileBuffer( FileHandle theFile |
| , const unsigned int toRead |
| , XMLByte* const toFill) |
| { |
| unsigned long bytesRead; |
| if (!::ReadFile(theFile, toFill, toRead, &bytesRead, 0)) |
| ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotReadFromFile); |
| return (unsigned int)bytesRead; |
| } |
| |
| |
| void XMLPlatformUtils::resetFile(FileHandle theFile) |
| { |
| // Seek to the start of the file |
| if (::SetFilePointer(theFile, 0, 0, FILE_BEGIN) == 0xFFFFFFFF) |
| ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotResetFile); |
| } |
| |
| |
| // --------------------------------------------------------------------------- |
| // XMLPlatformUtils: File Methods |
| // --------------------------------------------------------------------------- |
| void XMLPlatformUtils::writeToStdErr(const XMLCh* const toWrite) |
| { |
| // If handles never got opened, then eat the output, else output |
| if (gStdErr) |
| WriteUStrStdErr(toWrite); |
| } |
| |
| void XMLPlatformUtils::writeToStdErr(const char* const toWrite) |
| { |
| // If handles never got opened, then eat the output, else output |
| if (gStdErr) |
| WriteCharStrStdErr(toWrite); |
| } |
| |
| void XMLPlatformUtils::writeToStdOut(const XMLCh* const toWrite) |
| { |
| // If handles never got opened, then eat the output, else output |
| if (gStdOut) |
| WriteUStrStdOut(toWrite); |
| } |
| |
| void XMLPlatformUtils::writeToStdOut(const char* const toWrite) |
| { |
| // If handles never got opened, then eat the output, else output |
| if (gStdOut) |
| WriteCharStrStdOut(toWrite); |
| } |
| |
| |
| |
| // --------------------------------------------------------------------------- |
| // XMLPlatformUtils: File system methods |
| // --------------------------------------------------------------------------- |
| XMLCh* XMLPlatformUtils::getBasePath(const XMLCh* const srcPath) |
| { |
| // |
| // NOTE: THe path provided has always already been opened successfully, |
| // so we know that its not some pathological freaky path. |
| // |
| // 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(srcPath, bufSize, tmpPath, &namePart)) |
| return 0; |
| |
| // Cap it off at the name part, leaving just the full path |
| if (namePart) |
| *namePart = 0; |
| |
| // Return a copy of the path |
| return XMLString::replicate(tmpPath); |
| } |
| else |
| { |
| // Transcode the incoming string |
| char* tmpSrcPath = XMLString::transcode(srcPath); |
| ArrayJanitor<char> janSrcPath(tmpSrcPath); |
| |
| // 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; |
| |
| // Cap it off at the name part, leaving just the full path |
| if (namePart) |
| *namePart = 0; |
| |
| // Return a transcoded copy of the path |
| return XMLString::transcode(tmpPath); |
| } |
| } |
| |
| bool XMLPlatformUtils::isRelative(const XMLCh* const toCheck) |
| { |
| // 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 |
| // its a remote file. |
| // |
| if ((toCheck[0] == chBackSlash) && (toCheck[1] == chBackSlash)) |
| return false; |
| |
| // Else assume its a relative path |
| return true; |
| } |
| |
| |
| |
| // --------------------------------------------------------------------------- |
| // XMLPlatformUtils: Timing Methods |
| // --------------------------------------------------------------------------- |
| unsigned long XMLPlatformUtils::getCurrentMillis() |
| { |
| return (unsigned long)::GetTickCount(); |
| } |
| |
| |
| |
| // --------------------------------------------------------------------------- |
| // Mutex methods |
| // --------------------------------------------------------------------------- |
| void XMLPlatformUtils::closeMutex(void* const mtxHandle) |
| { |
| if (!::CloseHandle(mtxHandle)) |
| ThrowXML(XMLPlatformUtilsException, XML4CExcepts::Mutex_CouldNotClose); |
| } |
| |
| |
| void XMLPlatformUtils::lockMutex(void* const mtxHandle) |
| { |
| unsigned int res = ::WaitForSingleObject(mtxHandle, INFINITE); |
| if (res == WAIT_FAILED) |
| ThrowXML(XMLPlatformUtilsException, XML4CExcepts::Mutex_CouldNotLock); |
| } |
| |
| |
| void* XMLPlatformUtils::makeMutex() |
| { |
| HANDLE hRet = ::CreateMutex(0, 0, 0); |
| if (!hRet) |
| ThrowXML(XMLPlatformUtilsException, XML4CExcepts::Mutex_CouldNotCreate); |
| return hRet; |
| } |
| |
| |
| void XMLPlatformUtils::unlockMutex(void* const mtxHandle) |
| { |
| if (!::ReleaseMutex(mtxHandle)) |
| ThrowXML(XMLPlatformUtilsException, XML4CExcepts::Mutex_CouldNotUnlock); |
| } |
| |
| |
| // --------------------------------------------------------------------------- |
| // Miscellaneous synchronization methods |
| // --------------------------------------------------------------------------- |
| void* |
| XMLPlatformUtils::compareAndSwap( void** toFill |
| , const void* const newValue |
| , const void* const toCompare) |
| { |
| // |
| // Windows supports InterlockedCompareExchange only on Windows 98, NT 4.0, |
| // and newer. Not on Win 95. So we are back to using assembler. |
| // |
| #if defined(DEVENV_VCPP) |
| |
| void* result; |
| __asm |
| { |
| mov eax, toCompare; |
| mov ebx, newValue; |
| mov ecx, toFill |
| lock cmpxchg [ecx], ebx; |
| mov result, eax; |
| } |
| return result; |
| |
| #elif defined(XML_IBMVAW32) |
| |
| // <TBD> Why is this not using the interlocked call below? |
| void *retval = *toFill; |
| if( *toFill == toCompare) |
| *toFill = (void *) newValue; |
| return retVal; |
| |
| #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 ::InterlockedCompareExchange |
| ( |
| toFill |
| , (void*)newValue |
| , (void*)toCompare |
| ); |
| |
| #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. |
| // |
| // <TBD> For now we return zero, but later we will return the desired type |
| // of accessor object. |
| // |
| XMLNetAccessor* XMLPlatformUtils::makeNetAccessor() |
| { |
| return 0; |
| } |
| |
| |
| // |
| // 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) |
| { |
| #if defined (XML_USE_INMEMORY_MSGLOADER) |
| return new InMemMsgLoader(msgDomain); |
| #elif defined (XML_USE_WIN32_MSGLOADER) |
| return new Win32MsgLoader(msgDomain); |
| #else |
| #error You must provide a message loader |
| #endif |
| } |
| |
| |
| // |
| // 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) |
| char tmpBuf[4096]; |
| if (!::GetEnvironmentVariableA("ICU_DATA", tmpBuf, 4096)) |
| { |
| strcpy(tmpBuf, fgLibLocation); |
| strcat(tmpBuf, "intlFiles\\Locales\\"); |
| ICUTransService::setICUPath(tmpBuf); |
| } |
| return new ICUTransService; |
| #elif defined (XML_USE_WIN32_TRANSCODER) |
| return new Win32TransService; |
| #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. |
| // |
| void XMLPlatformUtils::platformInit() |
| { |
| // |
| // Lets get our own DLL path and store it. The fgLibLocation static |
| // member must be filled in with the path to the shared Lib or DLL |
| // so that other code can find any files relative to it. |
| // |
| HINSTANCE hmod = ::GetModuleHandleA(XML4C_DLLName); |
| if (!hmod) |
| { |
| // |
| // If we didn't find it, its probably because its a development |
| // build which is built as separate DLLs, so lets look for the DLL |
| // that we are part of. |
| // |
| static const char* const privDLLName = "IXUTIL"; |
| hmod = ::GetModuleHandle(privDLLName); |
| |
| // If neither exists, then we give up |
| if (!hmod) |
| panic(Panic_CantFindLib); |
| } |
| |
| // |
| // Get the path to our module. We explicitly get the ASCII version here |
| // since its stored as ASCII (or the local code page to be more specific, |
| // so it might be EBCDIC on some platforms.) |
| // |
| char tmpBuf[MAX_PATH + 1]; |
| if (!::GetModuleFileNameA(hmod, tmpBuf, MAX_PATH)) |
| panic(Panic_CantFindLib); |
| |
| // Find the last separator in the list and put a null in the next char |
| char* sepPtr = 0; |
| sepPtr = strrchr(tmpBuf, '\\'); |
| if (sepPtr) |
| *(sepPtr+1)= 0; |
| const unsigned int pathLen = strlen(tmpBuf); |
| |
| // Allocate a buffer and copy the text into it. Then store it in the static |
| char* actualBuf = new char[pathLen + 1]; |
| strcpy(actualBuf, tmpBuf); |
| fgLibLocation = actualBuf; |
| |
| // |
| // 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); |
| |
| // |
| // Ok, we have to do a little dance here to determine if we have any |
| // standard output handles. First we open up the potentially redirected |
| // standard handles. |
| // |
| gStdOut = ::GetStdHandle(STD_OUTPUT_HANDLE); |
| gStdErr = ::GetStdHandle(STD_ERROR_HANDLE); |
| |
| // |
| // If we got the handles, then get the console mode for them. If this |
| // fails, then assume for the time being that they are just redirected |
| // files. |
| // |
| // Above, when they are actually used, if they fail because of an |
| // invalid handle error, the gStdOut and gStdErr handles will get zeroed |
| // out all further output will be eaten. |
| // |
| DWORD dummyParm; |
| if (gStdOut) |
| { |
| if (!::GetConsoleMode(gStdOut, &dummyParm)) |
| gStdOutRedir = true; |
| } |
| |
| if (gStdErr) |
| { |
| if (!::GetConsoleMode(gStdErr, &dummyParm)) |
| gStdErrRedir = true; |
| } |
| } |