223 lines
6.7 KiB
C++
223 lines
6.7 KiB
C++
|
//=============================================================================
|
||
|
// 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;
|
||
|
}
|
||
|
}
|