|
|
//------------------------------------------------------------------------------
//
// File: impfile.cpp
// Copyright (C) 1995-1997 Microsoft Corporation
// All rights reserved.
//
// Purpose:
// Implementation of CLocImpFile, which provides the ILocFile interface for
// the parser.
//
// MAJOR IMPLEMENTATION FILE.
//
// Owner:
//
//------------------------------------------------------------------------------
#include "stdafx.h"
#include "dllvars.h"
#include "resource.h"
#include "impfile.h"
#include "impparse.h"
#include "xml_supp.h"
# define MAX_BUFFER 8192
// TODO: Format constants go here.
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Constructor for CLocImpFile.
//------------------------------------------------------------------------------
CLocImpFile::CLocImpFile( ILocParser *pParentClass) // Pointer to parent class, normally NULL.
{ //
// C.O.M. initialization
//
m_pParentClass = pParentClass; m_ulRefCount = 0;
//
// IMP file initialization
//
m_pOpenSourceFile = NULL;
m_pReporter = NULL; m_FileType = ftMNCFileType;
AddRef(); IncrementClassCount(); m_dwCountOfStringTables = 0; m_pstmSourceString = NULL; m_pstgSourceStringTable = NULL; m_pstgSourceParent = NULL; m_pstmTargetString = NULL; m_pstgTargetStringTable = NULL; m_pstgTargetParent = NULL;
m_bXMLBased = false;
// Format initialization.
// TODO: initialize implementation member variables here.
return; } // end of CLocImpFile::CLocImpFile()
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Destructor for CLocImpFile.
//------------------------------------------------------------------------------
CLocImpFile::~CLocImpFile() { DEBUGONLY(AssertValid());
if (m_pOpenSourceFile != NULL) { m_pOpenSourceFile->Close(); delete m_pOpenSourceFile; }
DecrementClassCount();
// Format deinitialization.
// TODO: perform any implementation cleanup here.
return; } // end of CLocImpFile::~CLocImpFile()
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Increment the object reference count. Return the new reference count.
//------------------------------------------------------------------------------
ULONG CLocImpFile::AddRef() { if (m_pParentClass != NULL) { m_pParentClass->AddRef(); }
return ++m_ulRefCount; } // end of CLocImpFile::AddRef()
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Decrement the object reference count. If it goes to 0, delete the object.
// Return the new reference count.
//------------------------------------------------------------------------------
ULONG CLocImpFile::Release() { LTASSERT(m_ulRefCount != 0);
if (m_pParentClass != NULL) { m_pParentClass->Release(); }
m_ulRefCount--; if (0 == m_ulRefCount) { delete this; return 0; }
return m_ulRefCount; } // end of CLocImpFile::Release()
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Query whether this object supports a given interface.
//
// Return values: some kind of result code
// ppvObj will point to this object if it supports the desired
// interface, be NULL if not.
//------------------------------------------------------------------------------
HRESULT CLocImpFile::QueryInterface( REFIID iid, // Desired interface.
LPVOID *ppvObj) // Return pointer to object with interface.
// Note that it's a hidden double pointer.
{ LTASSERT(ppvObj != NULL);
if (m_pParentClass != NULL) { return m_pParentClass->QueryInterface(iid, ppvObj); } else { SCODE scRetVal = E_NOINTERFACE;
*ppvObj = NULL;
if (IID_IUnknown == iid) { *ppvObj = (IUnknown *)this; scRetVal = S_OK; } else if (IID_ILocFile == iid) { *ppvObj = (ILocFile *)this; scRetVal = S_OK; }
if (S_OK == scRetVal) { AddRef(); } return ResultFromScode(scRetVal); } } // end of CLocImpFile::QueryInterface()
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Check object for validity. Asserts if not! (debug only)
//------------------------------------------------------------------------------
void CLocImpFile::AssertValidInterface() const { AssertValid();
return; } // end of CLocImpFile::AssertValidInterface()
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Open the file and make sure it is the correct type. Return TRUE if it is,
// FALSE if not or on error.
//------------------------------------------------------------------------------
BOOL CLocImpFile::OpenFile( const CFileSpec &fsFileSpec, // Name of file to open.
CReporter &Reporter) // Reporter object for messages.
{ DEBUGONLY(fsFileSpec.AssertValid()); DEBUGONLY(Reporter.AssertValid());
const CPascalString &pstrFileName = fsFileSpec.GetFileName(); BOOL fRetVal = FALSE;
LTTRACEPOINT("OpenFile()"); // Set reporter pointer for the duration of this function.
m_pReporter = &Reporter;
try { CFileException excFile;
m_pstrFileName = pstrFileName; // Initialize source filename.
m_idFile = fsFileSpec.GetFileId(); if (m_pOpenSourceFile != NULL) { // If source file pointer seems to be open already, close it.
m_pOpenSourceFile->Close(); delete m_pOpenSourceFile; m_pOpenSourceFile = NULL; }
// Open the source file. Doesn't throw an exception if the open
// fails, but does return FALSE and put the info in an exception
// structure if you supply one.
m_pOpenSourceFile = new CLFile; fRetVal = m_pOpenSourceFile->Open(m_pstrFileName, CFile::modeRead | CFile::shareDenyNone, &excFile); if (!fRetVal) { ReportException(&excFile); m_pOpenSourceFile->Abort(); delete m_pOpenSourceFile; m_pOpenSourceFile = NULL; // fRetCode is already FALSE.
} else { // Verify() assumes it is in a try/catch frame.
fRetVal = Verify(); } } catch(CException *e) { ReportException(e); delete m_pOpenSourceFile; m_pOpenSourceFile = NULL; fRetVal = FALSE; // m_pReporter will be NULLed by normal cleanup code below.
e->Delete(); } catch(...) { // Reset the reporter pointer, no idea if it will still be valid by
// the time the destructor gets called. The only other thing that
// needs to be cleaned up is the source file, which will be handled in
// the destructor.
m_pReporter = NULL; throw; }
m_pReporter = NULL;
return fRetVal; } // end of CLocImpFile::OpenFile()
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Return the file type (a ft* constant from impfile.h). If you only have one
// file type, you can just return it directly.
//------------------------------------------------------------------------------
FileType CLocImpFile::GetFileType() const { return m_FileType; } // end of CLocImpFile::GetFileType()
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Return the file description in strDesc, according to the file type. If you
// have only one file type, you can just return a string directly.
//------------------------------------------------------------------------------
void CLocImpFile::GetFileTypeDescription( CLString &strDesc) // Place to return file description string.
const { LTVERIFY(strDesc.LoadString(g_hDll, IDS_IMP_FILE_DESC)); return; } // end of CLocImpFile::GetFileTypeDescription()
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Return the names of any associated files as a list of strings in lstFiles.
// Returns TRUE if there are any, FALSE if not.
//------------------------------------------------------------------------------
BOOL CLocImpFile::GetAssociatedFiles( CStringList &lstFiles) // Return associated file names here.
const { DEBUGONLY(lstFiles.AssertValid()); LTASSERT(lstFiles.GetCount() == 0);
// TODO: If your files have associated files, put them in lstFiles here.
UNREFERENCED_PARAMETER(lstFiles);
return FALSE; } // end of CLocImpFile::GetAssociatedFiles()
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Enumerate all the localizable items in this file. Returns TRUE on success,
// FALSE on error.
//------------------------------------------------------------------------------
BOOL CLocImpFile::EnumerateFile( CLocItemHandler &ihItemHandler, // Localizable-item handler and
// reporter object all in one!
const CLocLangId &lid, // Source language ID object.
const DBID &dbidFileId) // Database ID of file, used as parent
// for all top-level items in the
// file.
{ DEBUGONLY(ihItemHandler.AssertValid()); DEBUGONLY(lid.AssertValid()); DEBUGONLY(dbidFileId.AssertValid());
LTTRACEPOINT("EnumerateFile()");
// Set reporter pointer for the duration of this function.
m_pReporter = &ihItemHandler;
if (NULL == m_pOpenSourceFile) { // Source file isn't open, whoops.
LTASSERT(0 && "Source file isn't open in CLocImpFile::EnumerateFile()"); return FALSE; }
// Retrieve and store the ANSI code page value. Note that some types
// of files use OEM code pages instead, or even use both. To get the
// OEM code page, do GetCodePage(cpDos) instead.
m_cpSource = lid.GetCodePage(cpAnsi);
BOOL bRet = TRUE;
try { bRet = EnumerateStrings(ihItemHandler,dbidFileId,FALSE); } catch(CException *e) { ReportException(e); bRet = FALSE; // m_pReporter will be NULLed by normal cleanup code below.
e->Delete(); } catch (...) { // Reset the reporter pointer, no idea if it will still be valid by
// the time the destructor gets called. Reset the process pointer,
// since it definitely won't be valid! The only other thing that
// needs to be cleaned up is the source file, which will be handled in
// the destructor.
m_pReporter = NULL; throw; }
m_pReporter = NULL; // Reset reporter pointer.
return bRet; } // end of CLocImpFile::EnumerateFile()
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Create a new target file be replacing resources in the source file with the
// localized items from Espresso.
//------------------------------------------------------------------------------
BOOL CLocImpFile::GenerateFile( const CPascalString &pstrTargetFile,// Name of target file.
CLocItemHandler &ihItemHandler, // Localizable-item handler and
// reporter object all in one!
const CLocLangId &lidSource, // Source language ID object.
const CLocLangId &lidTarget, // Target language ID object.
const DBID &dbidParent) // Database ID of file, used as
// parent for all top-level items
// in the file.
{ DEBUGONLY(pstrTargetFile.AssertValid()); DEBUGONLY(ihItemHandler.AssertValid()); DEBUGONLY(lidSource.AssertValid()); DEBUGONLY(lidTarget.AssertValid()); DEBUGONLY(dbidParent.AssertValid());
BOOL fRetVal = FALSE;
// Set reporter pointer for the duration of this function.
m_pReporter = &ihItemHandler;
if (NULL == m_pOpenSourceFile) { // Source file isn't open, whoops.
LTASSERT(0 && "Source file isn't open in CLocImpFile::GenerateFile()"); return FALSE; }
// Retrieve and store the ANSI code page values for the source and target
// files. Note that some types of files use OEM code pages instead, or
// even use both. To get the OEM code page, do GetCodePage(cpDos) instead.
m_cpSource = lidSource.GetCodePage(cpAnsi); m_cpTarget = lidTarget.GetCodePage(cpAnsi);
try { m_pstrTargetFile = pstrTargetFile; // Initialize target filename.
CFileStatus fsFileStatus;
CLFile::CopyFile(m_pstrFileName,m_pstrTargetFile,FALSE); CLFile::GetStatus(m_pstrTargetFile, fsFileStatus); if(fsFileStatus.m_attribute & CFile::readOnly) { fsFileStatus.m_attribute &= ~CFile::readOnly; CLFile::SetStatus(m_pstrTargetFile, fsFileStatus); }
fRetVal = EnumerateStrings(ihItemHandler,dbidParent,TRUE); } catch(CException *e) { ReportException(e, ImpEitherError); fRetVal = FALSE; // m_pReporter will be NULLed by normal cleanup code.
e->Delete(); } catch(...) { // Generic exception handling is needed here because otherwise
// target file will not be cleaned up. Also, no idea if reporter
// pointer will still be valid by the time the destructor is
// called. The process pointer definitely won't be valid, so reset
// it too. The source file will be cleaned up by the destructor.
m_pReporter = NULL; throw; }
// Cleanup.
if (!fRetVal) { try { // Nuke the target file if the generate failed.
CLFile::Remove(pstrTargetFile); } catch(CException *e) { ReportException(e, ImpTargetError); // fRetVal is already FALSE
// m_pReporter will be NULLed by normal cleanup code.
e->Delete(); } catch(...) { // Generic exception handling is needed here because otherwise
// target file will not be cleaned up. Also, no idea if reporter
// pointer will still be valid by the time the destructor is
// called. The process pointer is already NULL. The source file
// will be cleaned up by the destructor.
m_pReporter = NULL; throw; } }
// Normal cleanup code.
m_pReporter = NULL; // Reset reporter pointer.
return fRetVal; } // end of CLocImpFile::GenerateFile()
//------------------------------------------------------------------------------
//
// TODO:
// Verify that a file is a ???, as best we can. When we're reasonably sure,
// set the reporter confidence level to high -- until then, messages will be
// discarded, not displayed. This is also the place where m_FileType is set.
//
// Returns TRUE if so, FALSE if not or on error, or throws an exception.
//
// Normally there is need to catch exceptions in this function, they will
// be caught and handled by a higher level. To avoid memory leaks, consider
// using automatic variables or CByteArrays (as described and demonstrated in
// the utility function FindSignature() below) instead of dynamic allocation.
//------------------------------------------------------------------------------
BOOL CLocImpFile::Verify() { DEBUGONLY(AssertValid()); LTASSERT(m_pReporter != NULL); DEBUGONLY(m_pReporter->AssertValid());
// ...
// Set confidence level to high and return that we recognize this file.
m_pReporter->SetConfidenceLevel(CReporter::High); return TRUE; } // end of CLocImpFile::Verify()
//------------------------------------------------------------------------------
//
// Reports the exception described by *pException. Since the message can be
// retrieved directly from the exception, there is no need (as far as reporting
// goes) to catch or handle different kinds of exceptions separately. Normally,
// there is no reason for your code to call this function, since under normal
// circumstances you don't have to catch exceptions.
//
// THIS FUNCTION IS USED BY THE FRAMEWORK! DO NOT REMOVE IT!
//------------------------------------------------------------------------------
void CLocImpFile::ReportException( CException *pException, // Exception to be reported.
ImpFileError WhichFile) // Defaults to ImpSourceError (most common).
const { const UINT MAX_MESSAGE = 256;
CLString strContext; CLString strMessage; char *pszMessage;
LTASSERT(m_pReporter != NULL); DEBUGONLY(m_pReporter->AssertValid());
pszMessage = strMessage.GetBuffer(MAX_MESSAGE); LTASSERT(pszMessage != NULL); pException->GetErrorMessage(pszMessage, MAX_MESSAGE); strMessage.ReleaseBuffer();
switch (WhichFile) { case ImpNeitherError: // By convention, report errors not really in any
// file against the source file.
case ImpSourceError: m_pstrFileName.ConvertToCLString(strContext, CP_ACP); break;
case ImpTargetError: m_pstrTargetFile.ConvertToCLString(strContext, CP_ACP); break;
case ImpEitherError: { CLString strSource, strTarget;
m_pstrFileName.ConvertToCLString(strSource, CP_ACP); m_pstrTargetFile.ConvertToCLString(strTarget, CP_ACP);
strContext.Format(g_hDll, IDS_IMP_OR, (const char *) strSource, (const char *) strTarget); } break;
default: LTASSERT(0 && "WhichFile is bad during CLocImpFile::ReportException"); break; }
CContext ctx(strContext, m_idFile, otFile, vProjWindow);
m_pReporter->IssueMessage(esError, ctx, strMessage);
return; } // end of CLocImpFile::ReportException()
//------------------------------------------------------------------------------
//
// Reports a message to the user. Note that the message will be discarded
// unless the reporter's confidence level had been set high (see Verify()).
//------------------------------------------------------------------------------
void CLocImpFile::ReportMessage( MessageSeverity sev, // Severity of message.
// (esError, esWarning, esNote)
UINT nMsgId, // ID of string resource to load for message.
ImpFileError WhichFile) // Defaults to ImpSourceError (most common).
const { CLString strContext;
LTASSERT(m_pReporter != NULL); DEBUGONLY(m_pReporter->AssertValid());
switch (WhichFile) { case ImpNeitherError: // By convention, report errors not really in any
// file against the source file.
case ImpSourceError: m_pstrFileName.ConvertToCLString(strContext, CP_ACP); break;
case ImpTargetError: m_pstrTargetFile.ConvertToCLString(strContext, CP_ACP); break;
case ImpEitherError: { CLString strSource, strTarget;
m_pstrFileName.ConvertToCLString(strSource, CP_ACP); m_pstrTargetFile.ConvertToCLString(strTarget, CP_ACP);
strContext.Format(g_hDll, IDS_IMP_OR, (const char *) strSource, (const char *) strTarget); } break;
default: LTASSERT(0 && "WhichFile is bad during CLocImpFile::ReportMessage"); break; }
CContext ctx(strContext, m_idFile, otFile, vProjWindow);
m_pReporter->IssueMessage(sev, ctx, g_hDll, nMsgId);
return; } // end of CLocImpFile::ReportMessage()
#ifdef LTASSERT_ACTIVE
//------------------------------------------------------------------------------
//
// Asserts if the object is not valid. Any functions you add should probably
// call this function (in DEBUGONLY()) first thing -- see Verify() and Enum().
//------------------------------------------------------------------------------
void CLocImpFile::AssertValid() const { // Check base class.
CLObject::AssertValid();
// Check C.O.M. data. m_pParentClass should always be NULL.
// Correct range for m_ulRefCount is unknown, but make sure it hasn't
// wrapped around by checking for less than 100 (if we ever exceed
// 100 references from below, there's probably something wrong too!).
LTASSERT(NULL == m_pParentClass); LTASSERT(m_ulRefCount < 100);
// Check filename strings.
m_pstrFileName.AssertValid(); m_pstrTargetFile.AssertValid();
// If the file object pointers are non-NULL, check the objects.
if (m_pOpenSourceFile != NULL) { m_pOpenSourceFile->AssertValid(); } // If the reporter pointer is non-NULL, check the object.
if (m_pReporter != NULL) { m_pReporter->AssertValid(); }
// If the process object pointer is non-NULL, check the object.
// Make sure m_FileType is one of the valid types.
switch (m_FileType) { case ftMNCFileType: case ftUnknown: // TODO: add cases for all ft* constants in impfile.h here.
// case ftFoo1FileType:
// case ftFoo2FileType:
// These are all OK. Do nothing.
break;
default: // This is bad!
LTASSERT(0 && "m_FileType is bad during CLocImpFile::AssertValid()"); }
// Can't check code page values, they could be just about anything
// and still valid.
// TODO: check any checkable implementation member variables here.
return; } // end of CLocImpFile::AssertValid()
#endif // _DEBUG
//Creating a parent node
//ihItemHandler -> Required to send item
//dbidFileId -> Id of the parent of node
//pNewParentId -> New Id will be assigned can be used if this node has
// child
//szNodeRes -> Res ID of the node
//szNodeString -> String of the node
// <- Returns success or failure
BOOL CLocImpFile::CreateParentNode(CLocItemHandler & ihItemHandler, const DBID & dbidFileId, DBID & pNewParentId, const char * szNodeRes, const char * szNodeString) { BOOL fRetVal = TRUE; CLocItemSet isItemSet; CLocUniqueId uid; CPascalString pstrText,pstrId; try { CLocItem *pLocItem = new CLocItem(); pstrId.SetString(szNodeRes,strlen(szNodeRes),m_cpSource); uid.GetResId().SetId(pstrId); pstrText.SetString(szNodeString,strlen(szNodeString),m_cpSource); uid.GetTypeId().SetId(pstrText);
uid.SetParentId(dbidFileId);
//set up pLocItem
pLocItem->SetUniqueId(uid);
pLocItem->SetFDisplayable(TRUE); pLocItem->SetFExpandable(TRUE); pLocItem->SetFNoResTable(TRUE); pLocItem->SetIconType(CIT::Expandable); //Add the node to Item set
isItemSet.Add(pLocItem); //Send node to espresso
fRetVal = ihItemHandler.HandleItemSet(isItemSet); // If OK, retrieve DBID.
if (fRetVal) { pNewParentId.Clear(); pNewParentId = pLocItem->GetMyDatabaseId(); } isItemSet.ClearItemSet(); } catch (CMemoryException *pMemoryException) { CLString strContext;
strContext.LoadString(g_hDll, IDS_MNC_GENERIC_LOCATION); m_pReporter->IssueMessage(esError, strContext, g_hDll, IDS_MNC_NO_MEMORY, g_locNull); fRetVal = FALSE; pMemoryException->Delete(); } catch(CException *pException) { ReportException(pException); pException->Delete(); fRetVal = FALSE; } return fRetVal;
}
//Creating a child node
//ihItemHandler -> Required to send item
//dbidFileId -> Id of the parent of node
//pNewParentId -> New Id to be use for items belonging to this child
//szNodeRes -> Res ID of the node
//szNodeString -> String of the node
// <- Returns success or failure
BOOL CLocImpFile::CreateChildNode(CLocItemHandler & ihItemHandler, const DBID & dbidFileId, DBID & pNewParentId, const char * szNodeRes, const char * szNodeString) { BOOL fRetVal = TRUE; CLocItemSet isItemSet; CLocUniqueId uid; CPascalString pstrText,pstrId; try { CLocItem *pLocItem = new CLocItem(); pstrId.SetString(szNodeRes,strlen(szNodeRes),m_cpSource);
pstrText.SetString(szNodeString,strlen(szNodeString),m_cpSource); uid.GetResId().SetId(pstrId); uid.GetTypeId().SetId(pstrText); uid.SetParentId(dbidFileId);
//set up pLocItem
pLocItem->SetUniqueId(uid);
pLocItem->SetFDisplayable(TRUE); pLocItem->SetFExpandable(FALSE); pLocItem->SetFNoResTable(TRUE); pLocItem->SetIconType(CIT::String); //Add the node to Item set
isItemSet.Add(pLocItem); //Send node to espresso
fRetVal = ihItemHandler.HandleItemSet(isItemSet); // If OK, retrieve DBID.
if (fRetVal) { pNewParentId.Clear(); pNewParentId = pLocItem->GetMyDatabaseId(); } isItemSet.ClearItemSet(); } catch (CMemoryException *pMemoryException) { CLString strContext;
strContext.LoadString(g_hDll, IDS_MNC_GENERIC_LOCATION); m_pReporter->IssueMessage(esError, strContext, g_hDll, IDS_MNC_NO_MEMORY, g_locNull); fRetVal = FALSE; pMemoryException->Delete(); } catch(CException *pException) { ReportException(pException); pException->Delete(); fRetVal = FALSE; } return fRetVal;
}
BOOL CLocImpFile::EnumerateStrings(CLocItemHandler & ihItemHandler, const DBID & dbidFileId, BOOL fGenerating) { BOOL fRetVal = TRUE;
try { fRetVal = OpenStream(FALSE); if(!fRetVal) goto exit_clean;
if(fGenerating) fRetVal = OpenStream(TRUE); if(!fRetVal) goto exit_clean;
if (m_bXMLBased) fRetVal = ProcessXMLStrings(ihItemHandler,dbidFileId,fGenerating); else fRetVal = ProcessStrings(ihItemHandler,dbidFileId,fGenerating); } catch(CException *pException) { ReportException(pException); pException->Delete(); fRetVal = FALSE; } exit_clean: if(m_pstmSourceString) m_pstmSourceString->Release(); if(m_pstgSourceStringTable) m_pstgSourceStringTable->Release(); if(m_pstgSourceParent) m_pstgSourceParent->Release(); if(fGenerating) { if(m_pstmTargetString) m_pstmTargetString->Release(); if(m_pstgTargetStringTable) m_pstgTargetStringTable->Release(); if(m_pstgTargetParent) m_pstgTargetParent->Release(); } return fRetVal; }
BOOL CLocImpFile::ProcessStrings(CLocItemHandler & ihItemHandler, const DBID & dbidFileId, BOOL fGenerating) { DBID dbidParentId,dbidNodeId; BOOL fRetVal = TRUE; BOOL bUseBraces = ::IsConfiguredToUseBracesForStringTables();
fRetVal = CreateParentNode(ihItemHandler,dbidFileId,dbidParentId,"String Table","String Table"); for(DWORD i=0; i < m_dwCountOfStringTables;i++) { ULONG dwBytesRead; OLECHAR FAR* psz; char szTemp[MAX_BUFFER]; CLocItemSet lsItemSet; int nLength = 0;
dbidNodeId.Clear(); m_pstmSourceString->Read(&m_clsidSnapIn,sizeof(CLSID),&dwBytesRead); StringFromCLSID(m_clsidSnapIn,&psz); wcstombs(szTemp,psz,MAX_BUFFER); nLength = strlen(szTemp); LTASSERT((szTemp[0] == '{') && (szTemp[nLength - 1] == '}'));
// strip braces if configured so
CString strGUID(szTemp); if ( !bUseBraces && strGUID[0] == _T('{') && strGUID[strGUID.GetLength() - 1] == _T('}')) strGUID = strGUID.Mid(1, strGUID.GetLength() - 2);
fRetVal = CreateChildNode(ihItemHandler,dbidParentId,dbidNodeId,strGUID,strGUID); m_pstmSourceString->Read(&m_dwCountOfStrings,sizeof(DWORD),&dwBytesRead); if(fGenerating) { HRESULT hr; DWORD dwBytesWritten; hr = m_pstmTargetString->Write(&m_clsidSnapIn,sizeof(CLSID),&dwBytesWritten); hr = m_pstmTargetString->Write(&m_dwCountOfStrings,sizeof(DWORD),&dwBytesWritten); } for(DWORD j = 0;j < m_dwCountOfStrings;j++) { DWORD dwCharCount; m_pstmSourceString->Read(&m_dwID,sizeof(DWORD),&dwBytesRead); m_pstmSourceString->Read(&m_dwRefCount,sizeof(DWORD),&dwBytesRead); m_pstmSourceString->Read(&dwCharCount,sizeof(DWORD),&dwBytesRead); WCHAR *pString; pString = new WCHAR[dwCharCount + 1]; m_pstmSourceString->Read(pString,dwCharCount * 2,&dwBytesRead); pString[dwCharCount] = L'\0'; int nSize = WideCharToMultiByte(m_cpSource,0,pString,dwCharCount,szTemp,dwCharCount*2,NULL,NULL); szTemp[nSize] = '\0'; AddItemToSet(lsItemSet,dbidNodeId,m_dwID,szTemp); delete []pString; if(!fGenerating) fRetVal = ihItemHandler.HandleItemSet(lsItemSet); else fRetVal = GenerateStrings(ihItemHandler,lsItemSet); lsItemSet.ClearItemSet(); } }
return fRetVal; }
BOOL CLocImpFile::ProcessXMLStrings(CLocItemHandler & ihItemHandler, const DBID & dbidFileId, BOOL fGenerating) { DBID dbidParentId,dbidNodeId; BOOL bOK = TRUE; BOOL bUseBraces = ::IsConfiguredToUseBracesForStringTables();
// check if we have a table
if (m_spStringTablesNode == NULL) return FALSE;
// create node
bOK = CreateParentNode(ihItemHandler, dbidFileId, dbidParentId, "String Table", "String Table"); if (!bOK) return bOK;
// read the strings from XML document
CStringTableMap mapStringTables; HRESULT hr = ReadXMLStringTables(m_spStringTablesNode, mapStringTables); if (FAILED(hr)) return FALSE;
// iterate thru read data
CStringTableMap::iterator it; for (it = mapStringTables.begin(); it != mapStringTables.end(); ++it) { std::wstring wstrGUID = it->first; const CStringMap& rStrings = it->second;
dbidNodeId.Clear();
// convert 2 ansi
CString strGUID; wcstombs(strGUID.GetBuffer(wstrGUID.length()), wstrGUID.c_str(), wstrGUID.length()); strGUID.ReleaseBuffer();
// strip braces if configured so
if ( !bUseBraces && strGUID[0] == _T('{') && strGUID[strGUID.GetLength() - 1] == _T('}')) strGUID = strGUID.Mid(1, strGUID.GetLength() - 2);
bOK = CreateChildNode(ihItemHandler, dbidParentId, dbidNodeId, strGUID, strGUID); if (!bOK) return bOK;
// handle the strings in map
CStringMap::iterator its; for (its = rStrings.begin(); its != rStrings.end(); ++its) { DWORD dwID = its->first; std::wstring text = its->second;
DWORD dwCharCount = text.length(); CString strText; char *pBuffer = strText.GetBuffer(dwCharCount*2); if (pBuffer == NULL) return FALSE; int nSize = WideCharToMultiByte(m_cpSource, 0, text.c_str(), dwCharCount, pBuffer, dwCharCount*2, NULL, NULL); pBuffer[nSize] = '\0'; strText.ReleaseBuffer();
// use/update the string
CLocItemSet lsItemSet; AddItemToSet(lsItemSet, dbidNodeId, dwID, strText);
bOK = ihItemHandler.HandleItemSet(lsItemSet); if (!bOK) return bOK;
if(fGenerating) { CLocItem *pLocItem = lsItemSet.GetAt(0); if (!pLocItem) return FALSE;
std::wstring strNewVal = pLocItem->GetLocString().GetString(); hr = UpdateXMLString(m_spTargetStringTablesNode, wstrGUID, dwID, strNewVal); CString strMsg = strGUID; if (FAILED(hr)) return FALSE; } lsItemSet.ClearItemSet();
if (!bOK) return bOK; } }
// save XML document to the file
if (fGenerating) { hr = SaveXMLContents(m_pstrTargetFile, m_spTargetStringTablesNode); if (FAILED(hr)) return FALSE; }
return TRUE; }
BOOL CLocImpFile::AddItemToSet(CLocItemSet & isItemSet, const DBID &dbidNodeId, DWORD dwID, LPCSTR szText) { BOOL fRetVal = TRUE; CPascalString pstrText; CLocUniqueId uid; ULONG lItemType = 1; try { CLocItem * pNewItem = new CLocItem; pstrText.SetString(szText,strlen(szText),m_cpSource); uid.GetResId().SetId(dwID); uid.GetTypeId().SetId(lItemType); uid.SetParentId(dbidNodeId);
pNewItem->SetUniqueId(uid); CLocString lsString; pNewItem->SetIconType(CIT::String); lsString.SetString(pstrText); pNewItem->SetFDevLock(FALSE); pNewItem->SetFUsrLock(FALSE); pNewItem->SetFExpandable(FALSE); pNewItem->SetFDisplayable(FALSE); pNewItem->SetFNoResTable(FALSE); lsString.SetCodePageType(cpAnsi); lsString.SetStringType(CST::Text); pNewItem->SetLocString(lsString); isItemSet.Add(pNewItem); fRetVal = TRUE; } catch (CMemoryException *pMemoryException) { CLString strContext;
strContext.LoadString(g_hDll, IDS_MNC_GENERIC_LOCATION); m_pReporter->IssueMessage(esError, strContext, g_hDll, IDS_MNC_NO_MEMORY, g_locNull); fRetVal = FALSE; pMemoryException->Delete(); } catch(CException *pException) { ReportException(pException); pException->Delete(); fRetVal = FALSE; } return fRetVal; }
BOOL CLocImpFile::OpenStream(BOOL fGenerating) { BOOL fRetVal = TRUE; HRESULT hr;
if(!fGenerating) { hr = StgOpenStorage(m_pstrFileName,NULL,STGM_TRANSACTED | STGM_READ | STGM_SHARE_DENY_WRITE,NULL,0,&m_pstgSourceParent); if(!FAILED(hr)) { CPascalString pstrStorage,pstrStream; pstrStorage.SetString("String Table",strlen("String Table"),cpAnsi); pstrStream.SetString("Strings",strlen("Strings"),cpAnsi);
hr = m_pstgSourceParent->OpenStorage(pstrStorage,NULL,STGM_READ | STGM_SHARE_EXCLUSIVE,NULL,0,&m_pstgSourceStringTable); if(!FAILED(hr)) { HRESULT hr = m_pstgSourceStringTable->OpenStream(pstrStream,0,STGM_READ | STGM_SHARE_EXCLUSIVE,0,&m_pstmSourceString); if(!FAILED(hr)) { DWORD dwBytesRead; m_pstmSourceString->Read(&m_dwCountOfStringTables,sizeof(DWORD),&dwBytesRead); } else fRetVal = FALSE; } else { fRetVal = FALSE; } } else { // try to open this as XML document
m_spStringTablesNode.Release(); // release the old one (if such exist)
hr = OpenXMLStringTable(m_pstrFileName, &m_spStringTablesNode); if (SUCCEEDED(hr)) m_bXMLBased = true;
if (FAILED(hr)) { CLString strMessage, strFilePath;
m_pstrFileName.ConvertToCLString(strFilePath, CP_ACP); strMessage.Format(g_hDll, IDS_MSC_ERR_OPENSTORAGE, strFilePath); LTASSERT(m_pReporter != NULL); m_pReporter->IssueMessage(esError, CLString(g_hDll, IDS_MNC_GENERIC_LOCATION),strMessage);
fRetVal = FALSE; } } } else if (!m_bXMLBased) { hr = StgOpenStorage(m_pstrTargetFile,NULL,STGM_READWRITE | STGM_SHARE_EXCLUSIVE,NULL,0,&m_pstgTargetParent); if(!FAILED(hr)) { CPascalString pstrStorage,pstrStream; pstrStorage.SetString("String Table",strlen("String Table"),cpAnsi); pstrStream.SetString("Strings",strlen("Strings"),cpAnsi);
hr = m_pstgTargetParent->OpenStorage(pstrStorage,NULL,STGM_READWRITE | STGM_SHARE_EXCLUSIVE ,NULL,0,&m_pstgTargetStringTable); if(!FAILED(hr)) { HRESULT hr = m_pstgTargetStringTable->CreateStream(pstrStream, STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE,0,0,&m_pstmTargetString); if(!FAILED(hr)) { DWORD dwBytesRead; hr = m_pstmTargetString->Write(&m_dwCountOfStringTables,sizeof(DWORD),&dwBytesRead); } else fRetVal = FALSE; } else fRetVal = FALSE; } else fRetVal = FALSE; } else { // try to open this as XML document
m_spTargetStringTablesNode.Release(); // release the old one (if such exist)
hr = OpenXMLStringTable(m_pstrTargetFile, &m_spTargetStringTablesNode); if (FAILED(hr)) fRetVal = FALSE; } return fRetVal; }
BOOL CLocImpFile::GenerateStrings(CLocItemHandler & ihItemHandler, CLocItemSet & isItemSet) { BOOL fRetVal = TRUE; INT iNoOfElements = 0; DWORD dwBytesWritten,dwCharCount; WCHAR *pLocText; HRESULT hr;
try { if(ihItemHandler.HandleItemSet(isItemSet)) { while(iNoOfElements < isItemSet.GetSize()) { CLocItem *pLocItem; CPascalString pstrText;
pLocItem = isItemSet.GetAt(iNoOfElements);
hr = m_pstmTargetString->Write(&m_dwID,sizeof(DWORD),&dwBytesWritten); hr = m_pstmTargetString->Write(&m_dwRefCount,sizeof(DWORD),&dwBytesWritten); pstrText = pLocItem->GetLocString().GetString(); dwCharCount = pstrText.GetStringLength(); hr = m_pstmTargetString->Write(&dwCharCount,sizeof(DWORD),&dwBytesWritten); pLocText = pstrText.GetStringPointer(); hr = m_pstmTargetString->Write(pLocText,dwCharCount * 2,&dwBytesWritten); pstrText.ReleaseStringPointer(); iNoOfElements++; } } } catch(CException *pException) { ReportException(pException); pException->Delete(); fRetVal = FALSE; }
return fRetVal; }
|