| /* |
| * 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: Win32MsgLoader.cpp 568078 2007-08-21 11:43:25Z amassari $ |
| */ |
| |
| |
| // --------------------------------------------------------------------------- |
| // Includes |
| // --------------------------------------------------------------------------- |
| #include <xercesc/util/XercesDefs.hpp> |
| #include <xercesc/util/PlatformUtils.hpp> |
| #include <xercesc/util/XMLMsgLoader.hpp> |
| #include <xercesc/util/XMLString.hpp> |
| #include <xercesc/util/XMLUni.hpp> |
| #include <windows.h> |
| #include "Win32MsgLoader.hpp" |
| |
| |
| // Function prototypes |
| BOOL APIENTRY DllMain(HINSTANCE hModule, |
| DWORD ul_reason_for_call, |
| LPVOID lpReserved); |
| |
| |
| // --------------------------------------------------------------------------- |
| // Public Constructors and Destructor |
| // --------------------------------------------------------------------------- |
| HINSTANCE globalModuleHandle; |
| |
| BOOL APIENTRY DllMain(HINSTANCE hModule, |
| DWORD ul_reason_for_call, |
| LPVOID /*lpReserved*/) |
| { |
| switch (ul_reason_for_call) { |
| case DLL_PROCESS_ATTACH: |
| globalModuleHandle = hModule; |
| break; |
| case DLL_THREAD_ATTACH: |
| break; |
| case DLL_THREAD_DETACH: |
| break; |
| case DLL_PROCESS_DETACH: |
| break; |
| } |
| return TRUE; |
| } |
| |
| XERCES_CPP_NAMESPACE_BEGIN |
| |
| // --------------------------------------------------------------------------- |
| // Global module handle |
| // --------------------------------------------------------------------------- |
| Win32MsgLoader::Win32MsgLoader(const XMLCh* const msgDomain) : |
| |
| fDomainOfs(0) |
| , fModHandle(0) |
| , fMsgDomain(0) |
| { |
| // Try to get the module handle |
| fModHandle = globalModuleHandle; |
| if (!fModHandle) |
| { |
| // |
| // 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"; |
| fModHandle = ::GetModuleHandleA(privDLLName); |
| |
| // If neither exists, then we give up |
| if (!fModHandle) |
| { |
| // Probably have to call panic here |
| } |
| } |
| |
| // Store the domain name |
| fMsgDomain = XMLString::replicate(msgDomain, XMLPlatformUtils::fgMemoryManager); |
| |
| // And precalc the id offset we use for this domain |
| if (XMLString::equals(fMsgDomain, XMLUni::fgXMLErrDomain)) |
| fDomainOfs = 0; |
| else if (XMLString::equals(fMsgDomain, XMLUni::fgExceptDomain)) |
| fDomainOfs = 0x2000; |
| else if (XMLString::equals(fMsgDomain, XMLUni::fgValidityDomain)) |
| fDomainOfs = 0x4000; |
| else if (XMLString::equals(fMsgDomain, XMLUni::fgXMLDOMMsgDomain)) |
| fDomainOfs = 0x6000; |
| else |
| XMLPlatformUtils::panic(PanicHandler::Panic_UnknownMsgDomain); |
| } |
| |
| Win32MsgLoader::~Win32MsgLoader() |
| { |
| XMLPlatformUtils::fgMemoryManager->deallocate(fMsgDomain);//delete [] fMsgDomain; |
| } |
| |
| |
| // --------------------------------------------------------------------------- |
| // Implementation of the virtual message loader API |
| // --------------------------------------------------------------------------- |
| |
| // |
| // This is the method that actually does the work of loading a message from |
| // the attached resources. Note that we don't use LoadStringW here, since it |
| // won't work on Win98. So we go the next level down and do what LoadStringW |
| // would have done, since this will work on either platform. |
| // |
| bool Win32MsgLoader::loadMsg(const XMLMsgLoader::XMLMsgId msgToLoad |
| , XMLCh* const toFill |
| , const unsigned int maxChars) |
| { |
| // In case we error return, and they don't check it... |
| toFill[0] = 0; |
| |
| // Adjust the message id by the domain offset |
| const unsigned int theMsgId = msgToLoad + fDomainOfs; |
| |
| // |
| // Figure out the actual id the id, adjusting it by the domain offset. |
| // Then first we calculate the particular 16 string block that this id |
| // is in, and the offset within that block of the string in question. |
| // |
| const unsigned int theBlock = (theMsgId >> 4) + 1; |
| const unsigned int theOfs = theMsgId & 0x000F; |
| |
| // Try to find this resource. If we fail to find it, return false |
| HRSRC hMsgRsc = ::FindResourceEx |
| ( |
| fModHandle |
| , RT_STRING |
| , MAKEINTRESOURCE(theBlock) |
| , MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) |
| ); |
| if (!hMsgRsc) |
| return false; |
| |
| // We found it, so load the block. If this fails, also return a false |
| HGLOBAL hGbl = ::LoadResource(fModHandle, hMsgRsc); |
| if (!hGbl) |
| return false; |
| |
| // Lock this resource into memory. Again, if it fails, just return false |
| const XMLCh* pBlock = (const XMLCh*)::LockResource(hGbl); |
| if (!pBlock) |
| return false; |
| |
| // |
| // Look through the block for our desired message. Its stored such that |
| // the zeroth entry has the length minus the separator null. |
| // |
| for (unsigned int index = 0; index < theOfs; index++) |
| pBlock += *pBlock + 1; |
| |
| // Calculate how many actual chars we will end up with |
| const unsigned int actualChars = ((maxChars < *pBlock) ? maxChars : *pBlock); |
| |
| // Ok, finally now copy as much as we can into the caller's buffer |
| wcsncpy(toFill, pBlock + 1, actualChars); |
| toFill[actualChars] = 0; |
| |
| return true; |
| } |
| |
| |
| bool Win32MsgLoader::loadMsg(const XMLMsgLoader::XMLMsgId msgToLoad |
| , XMLCh* const toFill |
| , const unsigned int maxChars |
| , const XMLCh* const repText1 |
| , const XMLCh* const repText2 |
| , const XMLCh* const repText3 |
| , const XMLCh* const repText4 |
| , MemoryManager* const manager) |
| { |
| // Call the other version to load up the message |
| if (!loadMsg(msgToLoad, toFill, maxChars)) |
| return false; |
| |
| // And do the token replacement |
| XMLString::replaceTokens(toFill, maxChars, repText1, repText2, repText3, repText4, manager); |
| return true; |
| } |
| |
| |
| bool Win32MsgLoader::loadMsg(const XMLMsgLoader::XMLMsgId msgToLoad |
| , XMLCh* const toFill |
| , const unsigned int maxChars |
| , const char* const repText1 |
| , const char* const repText2 |
| , const char* const repText3 |
| , const char* const repText4 |
| , MemoryManager* const manager) |
| { |
| // |
| // Transcode the provided parameters and call the other version, |
| // which will do the replacement work. |
| // |
| XMLCh* tmp1 = 0; |
| XMLCh* tmp2 = 0; |
| XMLCh* tmp3 = 0; |
| XMLCh* tmp4 = 0; |
| |
| bool bRet = false; |
| if (repText1) |
| tmp1 = XMLString::transcode(repText1, manager); |
| if (repText2) |
| tmp2 = XMLString::transcode(repText2, manager); |
| if (repText3) |
| tmp3 = XMLString::transcode(repText3, manager); |
| if (repText4) |
| tmp4 = XMLString::transcode(repText4, manager); |
| |
| bRet = loadMsg(msgToLoad, toFill, maxChars, tmp1, tmp2, tmp3, tmp4, manager); |
| |
| if (tmp1) |
| manager->deallocate(tmp1);//delete [] tmp1; |
| if (tmp2) |
| manager->deallocate(tmp2);//delete [] tmp2; |
| if (tmp3) |
| manager->deallocate(tmp3);//delete [] tmp3; |
| if (tmp4) |
| manager->deallocate(tmp4);//delete [] tmp4; |
| |
| return bRet; |
| } |
| |
| XERCES_CPP_NAMESPACE_END |