GME  13
Win32MsgLoader.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  * 
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  * 
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: Win32MsgLoader.cpp 570552 2007-08-28 19:57:36Z amassari $
00020  */
00021 
00022 
00023 // ---------------------------------------------------------------------------
00024 //  Includes
00025 // ---------------------------------------------------------------------------
00026 #include <windows.h>
00027 
00028 #include <xercesc/util/PlatformUtils.hpp>
00029 #include <xercesc/util/XMLMsgLoader.hpp>
00030 #include <xercesc/util/XMLString.hpp>
00031 #include <xercesc/util/XMLUni.hpp>
00032 #include "Win32MsgLoader.hpp"
00033 
00034 
00035 //      Function prototypes
00036 BOOL APIENTRY DllMain(HINSTANCE hModule,
00037                              DWORD  ul_reason_for_call,
00038                              LPVOID lpReserved);
00039 
00040 
00041 // ---------------------------------------------------------------------------
00042 //  Public Constructors and Destructor
00043 // ---------------------------------------------------------------------------
00044 HINSTANCE globalModuleHandle;
00045 
00046 BOOL APIENTRY DllMain(HINSTANCE hModule,
00047                       DWORD  ul_reason_for_call,
00048                       LPVOID /*lpReserved*/)
00049 {
00050   switch (ul_reason_for_call) {
00051   case DLL_PROCESS_ATTACH:
00052     globalModuleHandle = hModule;
00053     break;
00054   case DLL_THREAD_ATTACH:
00055     break;
00056   case DLL_THREAD_DETACH:
00057     break;
00058   case DLL_PROCESS_DETACH:
00059     break;
00060   }
00061   return TRUE;
00062 }
00063 
00064 XERCES_CPP_NAMESPACE_BEGIN
00065 
00066 // ---------------------------------------------------------------------------
00067 //  Global module handle
00068 // ---------------------------------------------------------------------------
00069 Win32MsgLoader::Win32MsgLoader(const XMLCh* const msgDomain) :
00070 
00071     fDomainOfs(0)
00072     , fModHandle(0)
00073     , fMsgDomain(0)
00074 {
00075     // Try to get the module handle
00076     fModHandle = globalModuleHandle;
00077     if (!fModHandle)
00078     {
00079         //
00080         //  If we didn't find it, its probably because its a development
00081         //  build which is built as separate DLLs, so lets look for the DLL
00082         //  that we are part of.
00083         //
00084         static const char* const privDLLName = "IXUTIL";
00085         fModHandle = ::GetModuleHandleA(privDLLName);
00086 
00087         // If neither exists, then we give up
00088         if (!fModHandle)
00089         {
00090             // Probably have to call panic here
00091         }
00092     }
00093 
00094     // Store the domain name
00095     fMsgDomain = XMLString::replicate(msgDomain, XMLPlatformUtils::fgMemoryManager);
00096 
00097     // And precalc the id offset we use for this domain
00098     if (XMLString::equals(fMsgDomain, XMLUni::fgXMLErrDomain))
00099         fDomainOfs = 0;
00100     else if (XMLString::equals(fMsgDomain, XMLUni::fgExceptDomain))
00101         fDomainOfs = 0x2000;
00102     else if (XMLString::equals(fMsgDomain, XMLUni::fgValidityDomain))
00103         fDomainOfs = 0x4000;
00104     else if (XMLString::equals(fMsgDomain, XMLUni::fgXMLDOMMsgDomain))
00105         fDomainOfs = 0x6000;
00106     else
00107         XMLPlatformUtils::panic(PanicHandler::Panic_UnknownMsgDomain);
00108 }
00109 
00110 Win32MsgLoader::~Win32MsgLoader()
00111 {
00112     XMLPlatformUtils::fgMemoryManager->deallocate(fMsgDomain);//delete [] fMsgDomain;
00113 }
00114 
00115 
00116 // ---------------------------------------------------------------------------
00117 //  Implementation of the virtual message loader API
00118 // ---------------------------------------------------------------------------
00119 
00120 //
00121 //  This is the method that actually does the work of loading a message from
00122 //  the attached resources. Note that we don't use LoadStringW here, since it
00123 //  won't work on Win98. So we go the next level down and do what LoadStringW
00124 //  would have done, since this will work on either platform.
00125 //
00126 bool Win32MsgLoader::loadMsg(const  XMLMsgLoader::XMLMsgId  msgToLoad
00127                             ,       XMLCh* const            toFill
00128                             , const XMLSize_t               maxChars)
00129 {
00130     // In case we error return, and they don't check it...
00131     toFill[0] = 0;
00132 
00133     // Adjust the message id by the domain offset
00134     const unsigned int theMsgId = msgToLoad + fDomainOfs;
00135 
00136     //
00137     //  Figure out the actual id the id, adjusting it by the domain offset.
00138     //  Then first we calculate the particular 16 string block that this id
00139     //  is in, and the offset within that block of the string in question.
00140     //
00141     const unsigned int theBlock = (theMsgId >> 4) + 1;
00142     const unsigned int theOfs   = theMsgId & 0x000F;
00143 
00144     // Try to find this resource. If we fail to find it, return false
00145     HRSRC hMsgRsc = ::FindResourceEx
00146     (
00147         fModHandle
00148         , RT_STRING
00149         , MAKEINTRESOURCE(theBlock)
00150         , MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)
00151     );
00152     if (!hMsgRsc)
00153         return false;
00154 
00155     // We found it, so load the block. If this fails, also return a false
00156     HGLOBAL hGbl = ::LoadResource(fModHandle, hMsgRsc);
00157     if (!hGbl)
00158         return false;
00159 
00160     // Lock this resource into memory. Again, if it fails, just return false
00161     const XMLCh* pBlock = (const XMLCh*)::LockResource(hGbl);
00162     if (!pBlock)
00163         return false;
00164 
00165     //
00166     //  Look through the block for our desired message. Its stored such that
00167     //  the zeroth entry has the length minus the separator null.
00168     //
00169     for (unsigned int index = 0; index < theOfs; index++)
00170         pBlock += *pBlock + 1;
00171 
00172     // Calculate how many actual chars we will end up with
00173     const XMLSize_t actualChars = ((maxChars < (XMLSize_t)*pBlock) ? maxChars : (XMLSize_t)*pBlock);
00174 
00175     // Ok, finally now copy as much as we can into the caller's buffer
00176     wcsncpy(toFill, pBlock + 1, actualChars);
00177     toFill[actualChars] = 0;
00178 
00179     return true;
00180 }
00181 
00182 
00183 bool Win32MsgLoader::loadMsg(const  XMLMsgLoader::XMLMsgId  msgToLoad
00184                             ,       XMLCh* const            toFill
00185                             , const XMLSize_t               maxChars
00186                             , const XMLCh* const            repText1
00187                             , const XMLCh* const            repText2
00188                             , const XMLCh* const            repText3
00189                             , const XMLCh* const            repText4
00190                             , MemoryManager* const          manager)
00191 {
00192     // Call the other version to load up the message
00193     if (!loadMsg(msgToLoad, toFill, maxChars))
00194         return false;
00195 
00196     // And do the token replacement
00197     XMLString::replaceTokens(toFill, maxChars, repText1, repText2, repText3, repText4, manager);
00198     return true;
00199 }
00200 
00201 
00202 bool Win32MsgLoader::loadMsg(const  XMLMsgLoader::XMLMsgId  msgToLoad
00203                             ,       XMLCh* const            toFill
00204                             , const XMLSize_t               maxChars
00205                             , const char* const             repText1
00206                             , const char* const             repText2
00207                             , const char* const             repText3
00208                             , const char* const             repText4
00209                             , MemoryManager* const          manager)
00210 {
00211     //
00212     //  Transcode the provided parameters and call the other version,
00213     //  which will do the replacement work.
00214     //
00215     XMLCh* tmp1 = 0;
00216     XMLCh* tmp2 = 0;
00217     XMLCh* tmp3 = 0;
00218     XMLCh* tmp4 = 0;
00219 
00220     bool bRet = false;
00221     if (repText1)
00222         tmp1 = XMLString::transcode(repText1, manager);
00223     if (repText2)
00224         tmp2 = XMLString::transcode(repText2, manager);
00225     if (repText3)
00226         tmp3 = XMLString::transcode(repText3, manager);
00227     if (repText4)
00228         tmp4 = XMLString::transcode(repText4, manager);
00229 
00230     bRet = loadMsg(msgToLoad, toFill, maxChars, tmp1, tmp2, tmp3, tmp4, manager);
00231 
00232     if (tmp1)
00233         manager->deallocate(tmp1);//delete [] tmp1;
00234     if (tmp2)
00235         manager->deallocate(tmp2);//delete [] tmp2;
00236     if (tmp3)
00237         manager->deallocate(tmp3);//delete [] tmp3;
00238     if (tmp4)
00239         manager->deallocate(tmp4);//delete [] tmp4;
00240 
00241     return bRet;
00242 }
00243 
00244 XERCES_CPP_NAMESPACE_END