|
|
//=============================================================================
// File: rsrctmpl.cpp
// Author: a-jammar
// Covers: reading template from resources
//
// Copyright (c) 1998-1999 Microsoft Corporation
//
// This file contains the functions necessary to read the template information
// from the resources of this DLL. The template information is reconstructed
// from the resources so we can use the existing template parsing functions.
//=============================================================================
#include "stdafx.h"
#include "gather.h"
#include "gathint.h"
#include "resrc1.h"
static BOOL fTemplateLoaded = FALSE; static DWORD dwTemplateInfoLen = 0; static unsigned char * pTemplateInfo = NULL;
// This table contains the keywords found in the template stream.
#define KEYWORD_COUNT 19
char * KEYWORD_STRING[KEYWORD_COUNT] = { "node", "columns", "line", "field", "enumlines", "(", ")", "{", "}", ",", "\"basic\"", "\"advanced\"", "\"BASIC\"", "\"ADVANCED\"", "\"static\"", "\"LEXICAL\"", "\"VALUE\"", "\"NONE\"", "\"\"" };
//-----------------------------------------------------------------------------
// To support the way template information is loaded from resources now, we
// need to have an external entry point into this DLL (so we can get the
// default information like we template info from other DLLs).
//
// A pointer to the reconstructed template file is returned to the caller,
// as well as the length of the file. If a NULL pointer is passed as the
// parameter, the buffer containing the template file is deleted (to
// reclaim space).
//-----------------------------------------------------------------------------
void LoadTemplate(); extern "C" __declspec(dllexport) DWORD __cdecl GetTemplate(void ** ppBuffer) { TRY { if (!fTemplateLoaded) { LoadTemplate(); fTemplateLoaded = TRUE; }
if (ppBuffer == NULL) { if (pTemplateInfo) delete pTemplateInfo;
fTemplateLoaded = FALSE; dwTemplateInfoLen = 0; pTemplateInfo = NULL; return 0; } *ppBuffer = (void *)pTemplateInfo; return dwTemplateInfoLen; } CATCH_ALL(e) { #ifdef _DEBUG
e->ReportError(); #endif
} END_CATCH_ALL
return 0; }
//-----------------------------------------------------------------------------
// The LoadTemplate function needs to load the template information out of
// our resources, and create a buffer which contains the restored template
// file to return to our caller (through GetTemplate).
//-----------------------------------------------------------------------------
void LoadTemplate() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CMapWordToPtr mapNonLocalized; HRSRC hrsrcNFN; HGLOBAL hglbNFN; unsigned char *pData; WORD wID; CString strToken, *pstrToken;
// Load the non-localized strings from the custom resource type and create
// a map of ID to strings. Because these are non-localized strings, they
// will not be stored as UNICODE.
hrsrcNFN = FindResource(AfxGetResourceHandle(), _T("#1"), _T("MSINonLocalizedTokens"));
if(hrsrcNFN) hglbNFN = LoadResource(AfxGetResourceHandle(), hrsrcNFN);
if(hglbNFN) pData = (unsigned char *)LockResource(hglbNFN);
while (pData && *((WORD UNALIGNED *)pData)) { wID = (WORD)(((WORD)*pData++) << 8); // deal with the byte order explicitly to avoid
wID |= (WORD)*pData++; // endian problems.
pstrToken = new CString((char *)pData); pData += strlen((char *)pData) + 1;
if (pstrToken) mapNonLocalized.SetAt(wID, (void *)pstrToken); }
// Load the binary stream of token identifiers into memory.
HRSRC hrsrcNFB = FindResource(AfxGetResourceHandle(), _T("#1"), _T("MSITemplateStream")); HGLOBAL hglbNFB; unsigned char *pStream = NULL;
if(hrsrcNFB) hglbNFB = LoadResource(AfxGetResourceHandle(), hrsrcNFB); if(hglbNFB) pStream = (unsigned char *) LockResource(hglbNFB);
if (pStream != NULL) { // The first DWORD in the stream is the size of the original text file. We'll
// use this to allocate our buffer to store the reconstituted file.
DWORD dwSize; dwSize = ((DWORD)*pStream++) << 24; dwSize |= ((DWORD)*pStream++) << 16; dwSize |= ((DWORD)*pStream++) << 8; dwSize |= ((DWORD)*pStream++);
// The size stored with for an Ansi text file. We need to adjust for the
// fact that our reconstituted file will be UNICODE. We also want to add
// a word to the front of the stream to hold the UNICODE file marker (so
// we can use the same functions to read a file or this stream).
dwSize *= sizeof(TCHAR); dwSize += sizeof(WORD); pTemplateInfo = new unsigned char[dwSize]; dwTemplateInfoLen = 0; if (pTemplateInfo == NULL) return;
// Write the UNICODE file marker.
wID = 0xFEFF; memcpy(&pTemplateInfo[dwTemplateInfoLen], (void *)&wID, sizeof(WORD)); dwTemplateInfoLen += sizeof(WORD);
// Process the stream a token at a time.
while (pStream && *pStream) { if ((*pStream & 0x80) == 0x00) { // A byte with the high bit clear refers to a keyword. Look up the keyword
// from the table, and add it to the restored file.
wID = (WORD)(((WORD)*pStream++) - 1); ASSERT(wID <= KEYWORD_COUNT); if (wID <= KEYWORD_COUNT) strToken = KEYWORD_STRING[wID]; } else { wID = (WORD)(((WORD)*pStream++) << 8); // deal with the byte order explicitly to avoid
wID |= (WORD)*pStream++; // endian problems.
if ((wID & 0xC000) == 0x8000) { // A byte with the high bit set, but the next to high bit clear indicates
// the ID is actually a word, and should be used to get a non-localized
// string. Get the string out of the map we created and add it to the file.
if (mapNonLocalized.Lookup((WORD)(wID & 0x7FFF), (void *&)pstrToken)) strToken = *pstrToken; else ASSERT(FALSE); } else { // A byte with the two MSB set indicates that the ID is a word, and should
// be used to reference a localized string out of the string table in this
// module's resources. This string will be UNICODE.
VERIFY(strToken.LoadString((wID & 0x3FFF) + IDS_MSITEMPLATEBASE)); strToken = _T("\"") + strToken + _T("\""); } }
// Store the token on the end of our buffer. The data in this buffer must
// be UNICODE, so we'll need to convert the string if necessary.
if (dwTemplateInfoLen + strToken.GetLength() * sizeof(TCHAR) < dwSize) { memcpy(&pTemplateInfo[dwTemplateInfoLen], (void *)(LPCTSTR)strToken, strToken.GetLength() * sizeof(TCHAR)); dwTemplateInfoLen += strToken.GetLength() * sizeof(TCHAR); } else ASSERT(FALSE); } }
// Delete the contents of the lookup table.
for (POSITION pos = mapNonLocalized.GetStartPosition(); pos != NULL;) { mapNonLocalized.GetNextAssoc(pos, wID, (void *&)pstrToken); if (pstrToken) delete pstrToken; } }
|