2400 lines
		
	
	
		
			65 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			2400 lines
		
	
	
		
			65 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "catalog.h"
 | 
						|
#include "catmeta.h"
 | 
						|
#include "WriterGlobalHelper.h"
 | 
						|
#include "WriterGlobals.cpp"
 | 
						|
#include "mddefw.h"
 | 
						|
#include "iiscnfg.h"
 | 
						|
#include "wchar.h"
 | 
						|
#include "pudebug.h"
 | 
						|
 | 
						|
#define  MAX_FLAG_STRING_CHARS 1024
 | 
						|
 | 
						|
//
 | 
						|
// TODO: Since XML table also uses this, cant we reduce to one definition?
 | 
						|
//
 | 
						|
 | 
						|
static WCHAR * kByteToWchar[256] = 
 | 
						|
{
 | 
						|
    L"00",    L"01",    L"02",    L"03",    L"04",    L"05",    L"06",    L"07",    L"08",    L"09",    L"0a",    L"0b",    L"0c",    L"0d",    L"0e",    L"0f",
 | 
						|
    L"10",    L"11",    L"12",    L"13",    L"14",    L"15",    L"16",    L"17",    L"18",    L"19",    L"1a",    L"1b",    L"1c",    L"1d",    L"1e",    L"1f",
 | 
						|
    L"20",    L"21",    L"22",    L"23",    L"24",    L"25",    L"26",    L"27",    L"28",    L"29",    L"2a",    L"2b",    L"2c",    L"2d",    L"2e",    L"2f",
 | 
						|
    L"30",    L"31",    L"32",    L"33",    L"34",    L"35",    L"36",    L"37",    L"38",    L"39",    L"3a",    L"3b",    L"3c",    L"3d",    L"3e",    L"3f",
 | 
						|
    L"40",    L"41",    L"42",    L"43",    L"44",    L"45",    L"46",    L"47",    L"48",    L"49",    L"4a",    L"4b",    L"4c",    L"4d",    L"4e",    L"4f",
 | 
						|
    L"50",    L"51",    L"52",    L"53",    L"54",    L"55",    L"56",    L"57",    L"58",    L"59",    L"5a",    L"5b",    L"5c",    L"5d",    L"5e",    L"5f",
 | 
						|
    L"60",    L"61",    L"62",    L"63",    L"64",    L"65",    L"66",    L"67",    L"68",    L"69",    L"6a",    L"6b",    L"6c",    L"6d",    L"6e",    L"6f",
 | 
						|
    L"70",    L"71",    L"72",    L"73",    L"74",    L"75",    L"76",    L"77",    L"78",    L"79",    L"7a",    L"7b",    L"7c",    L"7d",    L"7e",    L"7f",
 | 
						|
    L"80",    L"81",    L"82",    L"83",    L"84",    L"85",    L"86",    L"87",    L"88",    L"89",    L"8a",    L"8b",    L"8c",    L"8d",    L"8e",    L"8f",
 | 
						|
    L"90",    L"91",    L"92",    L"93",    L"94",    L"95",    L"96",    L"97",    L"98",    L"99",    L"9a",    L"9b",    L"9c",    L"9d",    L"9e",    L"9f",
 | 
						|
    L"a0",    L"a1",    L"a2",    L"a3",    L"a4",    L"a5",    L"a6",    L"a7",    L"a8",    L"a9",    L"aa",    L"ab",    L"ac",    L"ad",    L"ae",    L"af",
 | 
						|
    L"b0",    L"b1",    L"b2",    L"b3",    L"b4",    L"b5",    L"b6",    L"b7",    L"b8",    L"b9",    L"ba",    L"bb",    L"bc",    L"bd",    L"be",    L"bf",
 | 
						|
    L"c0",    L"c1",    L"c2",    L"c3",    L"c4",    L"c5",    L"c6",    L"c7",    L"c8",    L"c9",    L"ca",    L"cb",    L"cc",    L"cd",    L"ce",    L"cf",
 | 
						|
    L"d0",    L"d1",    L"d2",    L"d3",    L"d4",    L"d5",    L"d6",    L"d7",    L"d8",    L"d9",    L"da",    L"db",    L"dc",    L"dd",    L"de",    L"df",
 | 
						|
    L"e0",    L"e1",    L"e2",    L"e3",    L"e4",    L"e5",    L"e6",    L"e7",    L"e8",    L"e9",    L"ea",    L"eb",    L"ec",    L"ed",    L"ee",    L"ef",
 | 
						|
    L"f0",    L"f1",    L"f2",    L"f3",    L"f4",    L"f5",    L"f6",    L"f7",    L"f8",    L"f9",    L"fa",    L"fb",    L"fc",    L"fd",    L"fe",    L"ff"
 | 
						|
};
 | 
						|
 | 
						|
static eESCAPE kWcharToEscape[256] = 
 | 
						|
{
 | 
						|
  /* 00-0F */ eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eNoESCAPE,            eNoESCAPE,            eESCAPEillegalxml,    eESCAPEillegalxml,    eNoESCAPE,            eESCAPEillegalxml,    eESCAPEillegalxml,
 | 
						|
  /* 10-1F */ eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,    eESCAPEillegalxml,
 | 
						|
  /* 20-2F */ eNoESCAPE,            eNoESCAPE,            eESCAPEquote,         eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eESCAPEamp,           eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,
 | 
						|
  /* 30-3F */ eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eESCAPElt,            eNoESCAPE,            eESCAPEgt,            eNoESCAPE,
 | 
						|
  /* 40-4F */ eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,
 | 
						|
  /* 50-5F */ eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,
 | 
						|
  /* 60-6F */ eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,
 | 
						|
  /* 70-7F */ eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE, 
 | 
						|
  /* 80-8F */ eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,   
 | 
						|
  /* 90-9F */ eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,   
 | 
						|
  /* A0-AF */ eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,   
 | 
						|
  /* B0-BF */ eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,   
 | 
						|
  /* C0-CF */ eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,   
 | 
						|
  /* D0-DF */ eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,   
 | 
						|
  /* E0-EF */ eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,   
 | 
						|
  /* F0-FF */ eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE,            eNoESCAPE
 | 
						|
};
 | 
						|
 | 
						|
#define IsSecureMetadata(id,att) (((DWORD)(att) & METADATA_SECURE) != 0)
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    Gets the bin file name by querying the compiler. The compiler hands out
 | 
						|
    the latest valid bin file. Once we get the bin file name from the complier
 | 
						|
    we can assume that it is valid until we call release bin file on it.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    [in, optional] Compiler interface
 | 
						|
    [out]          Bin file name
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    HRESULT
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
HRESULT GetBinFile(IMetabaseSchemaCompiler*	i_pCompiler,
 | 
						|
				   LPWSTR*                  o_wszBinFile)
 | 
						|
{
 | 
						|
	HRESULT						hr			= S_OK;
 | 
						|
	ULONG						cch			= 0;
 | 
						|
	ISimpleTableDispenser2*		pISTDisp	= NULL;
 | 
						|
	IMetabaseSchemaCompiler*	pCompiler	= i_pCompiler;
 | 
						|
	
 | 
						|
	*o_wszBinFile = NULL;
 | 
						|
 | 
						|
	//
 | 
						|
	// GetBinFile relies on the fact that SetBinFile has been called at ReadAllData 
 | 
						|
	// See InitializeIISGlobalsToDefaults
 | 
						|
	//
 | 
						|
 | 
						|
	if(NULL == i_pCompiler)
 | 
						|
	{
 | 
						|
		//
 | 
						|
		// Get a pointer to the compiler to get the bin file name.
 | 
						|
		//
 | 
						|
 | 
						|
		hr = GetSimpleTableDispenser (WSZ_PRODUCT_IIS, 0, &pISTDisp);
 | 
						|
 | 
						|
		if(FAILED(hr))
 | 
						|
		{
 | 
						|
			DBGINFOW((DBG_CONTEXT,
 | 
						|
					  L"[ReleaseBinFile] GetSimpleTableDispenser failed with hr = 0x%x.\n",hr));
 | 
						|
			goto exit;
 | 
						|
		}
 | 
						|
 | 
						|
		hr = pISTDisp->QueryInterface(IID_IMetabaseSchemaCompiler,
 | 
						|
									  (LPVOID*)&pCompiler);
 | 
						|
 | 
						|
		if(FAILED(hr))
 | 
						|
		{
 | 
						|
			DBGINFOW((DBG_CONTEXT,
 | 
						|
					  L"[ReleaseBinFile] QueryInterface on compiler failed with hr = 0x%x.\n",hr));
 | 
						|
			goto exit;
 | 
						|
		}
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	hr = pCompiler->GetBinFileName(NULL,
 | 
						|
		                           &cch);
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
		DBGINFOW((DBG_CONTEXT,
 | 
						|
				  L"[GetBinFile] Unable to get the count of chars in the bin file name. IMetabaseSchemaCompiler::GetBinFileName failed with hr = 0x%x.\n",hr));
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
	*o_wszBinFile = new WCHAR[cch+1];
 | 
						|
	if(NULL == *o_wszBinFile)
 | 
						|
	{
 | 
						|
		hr = E_OUTOFMEMORY;
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
	hr = pCompiler->GetBinFileName(*o_wszBinFile,
 | 
						|
		                           &cch);
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
		DBGINFOW((DBG_CONTEXT,
 | 
						|
				  L"[GetBinFile] Unable to get the bin file name. IMetabaseSchemaCompiler::GetBinFileName failed with hr = 0x%x.\n",hr));
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
	//
 | 
						|
	// If there is no bin file, GetBinFileName returns a null string i.e. L""
 | 
						|
	//
 | 
						|
 | 
						|
exit:
 | 
						|
 | 
						|
	if(NULL != pISTDisp)
 | 
						|
	{
 | 
						|
		pISTDisp->Release();
 | 
						|
	}
 | 
						|
 | 
						|
	if((NULL == i_pCompiler) && (NULL != pCompiler))
 | 
						|
	{
 | 
						|
        //
 | 
						|
        // We created it - release it.
 | 
						|
        //
 | 
						|
 | 
						|
		pCompiler->Release();
 | 
						|
	}
 | 
						|
 | 
						|
	if(FAILED(hr) && (NULL != *o_wszBinFile))
 | 
						|
	{
 | 
						|
		delete [] *o_wszBinFile;
 | 
						|
		*o_wszBinFile = NULL;
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	return hr;
 | 
						|
 | 
						|
} // GeBinFile
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    Releases the bin file name by from the compiler. Once release is called
 | 
						|
    on the bin file, the compiler releases locks on it, and is free to clean
 | 
						|
    it up and we cannot make the assumption that it will be valid.
 | 
						|
    The function also release the bin file name, which we assume has been 
 | 
						|
    allocated in GetBinFile
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    [in, optional] Compiler interface
 | 
						|
    [in,out]       Bin file name
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    HRESULT
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
void ReleaseBinFile(IMetabaseSchemaCompiler*	i_pCompiler,
 | 
						|
					LPWSTR*						io_wszBinFileName)
 | 
						|
{
 | 
						|
	ISimpleTableDispenser2*		pISTDisp   = NULL;
 | 
						|
	IMetabaseSchemaCompiler*	pCompiler  = i_pCompiler;
 | 
						|
	HRESULT                     hr         = S_OK; 
 | 
						|
 | 
						|
	if(NULL == *io_wszBinFileName)
 | 
						|
	{
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
	if(NULL == i_pCompiler)
 | 
						|
	{
 | 
						|
		//
 | 
						|
		// Get a pointer to the compiler to get the bin file name.
 | 
						|
		//
 | 
						|
 | 
						|
		hr = GetSimpleTableDispenser (WSZ_PRODUCT_IIS, 0, &pISTDisp);
 | 
						|
 | 
						|
		if(FAILED(hr))
 | 
						|
		{
 | 
						|
			DBGINFOW((DBG_CONTEXT,
 | 
						|
					  L"[ReleaseBinFile] GetSimpleTableDispenser failed with hr = 0x%x.\n",hr));
 | 
						|
			goto exit;
 | 
						|
		}
 | 
						|
 | 
						|
		hr = pISTDisp->QueryInterface(IID_IMetabaseSchemaCompiler,
 | 
						|
									  (LPVOID*)&pCompiler);
 | 
						|
 | 
						|
		if(FAILED(hr))
 | 
						|
		{
 | 
						|
			DBGINFOW((DBG_CONTEXT,
 | 
						|
					  L"[ReleaseBinFile] QueryInterface on compiler failed with hr = 0x%x.\n",hr));
 | 
						|
			goto exit;
 | 
						|
		}
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	pCompiler->ReleaseBinFileName(*io_wszBinFileName);
 | 
						|
 | 
						|
exit:
 | 
						|
 | 
						|
	if(NULL != pISTDisp)
 | 
						|
	{
 | 
						|
		pISTDisp->Release();
 | 
						|
	}
 | 
						|
 | 
						|
	if((NULL != pCompiler) && (NULL == i_pCompiler))
 | 
						|
	{
 | 
						|
        //
 | 
						|
        // We created it - release it.
 | 
						|
        //
 | 
						|
		pCompiler->Release();
 | 
						|
	}
 | 
						|
 | 
						|
	if(NULL != 	*io_wszBinFileName)
 | 
						|
	{
 | 
						|
		delete [] 	*io_wszBinFileName;
 | 
						|
		*io_wszBinFileName = NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	return;
 | 
						|
 | 
						|
} // ReleaseBinFile
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    Convert unsigned long to a sting.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    [in]   ULONG to convert to string
 | 
						|
    [out]  New stringised ULONG
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    HRESULT
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
HRESULT UnsignedLongToNewString(ULONG    i_ul,
 | 
						|
                                LPWSTR*  o_wszUl)
 | 
						|
{
 | 
						|
	WCHAR wszBufferDW[40];
 | 
						|
 | 
						|
	_ultow(i_ul, wszBufferDW, 10);
 | 
						|
 | 
						|
	*o_wszUl = new WCHAR[wcslen(wszBufferDW)+1];
 | 
						|
	if(NULL == *o_wszUl)
 | 
						|
	{
 | 
						|
		return E_OUTOFMEMORY;
 | 
						|
	}
 | 
						|
	wcscpy(*o_wszUl, wszBufferDW);
 | 
						|
 | 
						|
	return S_OK;
 | 
						|
 | 
						|
} // UnsignedLongToString
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    Copy String
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    [in]   String to copy
 | 
						|
    [out]  New string
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    HRESULT
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
HRESULT StringToNewString(LPWSTR   i_wsz,
 | 
						|
						  ULONG    i_cch,
 | 
						|
                          LPWSTR*  o_wsz)
 | 
						|
{
 | 
						|
    ULONG cb  = (i_cch+1)*sizeof(WCHAR);
 | 
						|
 | 
						|
    *o_wsz = new WCHAR[i_cch+1];
 | 
						|
    if(NULL == *o_wsz)
 | 
						|
    {
 | 
						|
        return E_OUTOFMEMORY;
 | 
						|
    }
 | 
						|
	memcpy(*o_wsz, i_wsz, cb);
 | 
						|
 | 
						|
    return S_OK;
 | 
						|
 | 
						|
} // StringToNewString
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    Create a new String and NULL terminate it.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    [in]   Count of chars (assume without null terminator) 
 | 
						|
    [out]  New string
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    HRESULT
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
HRESULT NewString(ULONG    cch,
 | 
						|
                  LPWSTR*  o_wsz)
 | 
						|
{
 | 
						|
	*o_wsz = new WCHAR[cch+1];
 | 
						|
	if(NULL == *o_wsz)
 | 
						|
	{
 | 
						|
		return E_OUTOFMEMORY;
 | 
						|
	}
 | 
						|
	**o_wsz = L'\0';
 | 
						|
 | 
						|
	return S_OK;
 | 
						|
 | 
						|
} // NewString
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    Reallocate more buffer for the string and copy old contents.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    [in]       Count of chars to grow (assume without null terminator) 
 | 
						|
    [in,out]   Current count of chars, gets updated to the new current count.
 | 
						|
    [out]      New string with extra allocation
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    HRESULT
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
HRESULT ReAllocateString(ULONG   i_chhToGrow,
 | 
						|
                         ULONG*  io_cchCurrent,
 | 
						|
						 LPWSTR* io_wsz)
 | 
						|
{
 | 
						|
	LPWSTR  wszTemp = NULL;
 | 
						|
	ULONG   cch     = *io_cchCurrent + i_chhToGrow;
 | 
						|
	HRESULT hr      = S_OK;
 | 
						|
 | 
						|
    hr = NewString(cch,
 | 
						|
	               &wszTemp);
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
	    return hr;
 | 
						|
	}
 | 
						|
 | 
						|
	if(NULL != *io_wsz)
 | 
						|
	{
 | 
						|
	    wcscpy(wszTemp, *io_wsz);
 | 
						|
		delete [] (*io_wsz);
 | 
						|
	}
 | 
						|
 | 
						|
	*io_wsz = wszTemp;
 | 
						|
	*io_cchCurrent = cch;
 | 
						|
 | 
						|
    return S_OK;
 | 
						|
 | 
						|
} // ReAllocateString
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    Constructor for CWriterGlobalHelper
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    None
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    None
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
CWriterGlobalHelper::CWriterGlobalHelper()
 | 
						|
{
 | 
						|
	m_pISTTagMetaByTableAndColumnIndexAndName	= NULL;
 | 
						|
	m_pISTTagMetaByTableAndColumnIndexAndValue  = NULL;
 | 
						|
	m_pISTTagMetaByTableAndColumnIndex	        = NULL;
 | 
						|
	m_pISTTagMetaByTableAndID                   = NULL;
 | 
						|
	m_pISTTagMetaByTableAndName                 = NULL;
 | 
						|
	m_pISTColumnMeta				            = NULL;
 | 
						|
	m_pISTColumnMetaByTableAndID	            = NULL;
 | 
						|
	m_pISTColumnMetaByTableAndName	            = NULL;
 | 
						|
	m_pISTTableMetaForMetabaseTables			= NULL;
 | 
						|
	m_cColKeyTypeMetaData			            = cCOLUMNMETA_NumberOfColumns;
 | 
						|
	m_wszTABLE_IIsConfigObject                  = wszTABLE_IIsConfigObject;
 | 
						|
	m_wszTABLE_MBProperty                       = wszTABLE_MBProperty;
 | 
						|
	m_iStartRowForAttributes                    = -1;
 | 
						|
	m_wszBinFileForMeta				            = NULL;
 | 
						|
	m_cchBinFileForMeta                         = 0;
 | 
						|
	m_wszIIS_MD_UT_SERVER                       = NULL;
 | 
						|
	m_cchIIS_MD_UT_SERVER                       = 0;
 | 
						|
	m_wszIIS_MD_UT_FILE                         = NULL;
 | 
						|
	m_cchIIS_MD_UT_FILE                         = 0;
 | 
						|
	m_wszIIS_MD_UT_WAM                          = NULL;
 | 
						|
	m_cchIIS_MD_UT_WAM                          = 0;
 | 
						|
	m_wszASP_MD_UT_APP                          = NULL;
 | 
						|
	m_cchASP_MD_UT_APP                          = 0;
 | 
						|
 | 
						|
} // Constructor
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    Destructor for CWriterGlobalHelper
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    None
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    None
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
CWriterGlobalHelper::~CWriterGlobalHelper()
 | 
						|
{
 | 
						|
	if(NULL != m_pISTTagMetaByTableAndColumnIndexAndName)
 | 
						|
	{
 | 
						|
		m_pISTTagMetaByTableAndColumnIndexAndName->Release();
 | 
						|
		m_pISTTagMetaByTableAndColumnIndexAndName = NULL;
 | 
						|
	}
 | 
						|
	if(NULL != m_pISTTagMetaByTableAndColumnIndexAndValue)
 | 
						|
	{
 | 
						|
		m_pISTTagMetaByTableAndColumnIndexAndValue->Release();
 | 
						|
		m_pISTTagMetaByTableAndColumnIndexAndValue = NULL;
 | 
						|
	}
 | 
						|
	if(NULL != m_pISTTagMetaByTableAndColumnIndex)
 | 
						|
	{
 | 
						|
		m_pISTTagMetaByTableAndColumnIndex->Release();
 | 
						|
		m_pISTTagMetaByTableAndColumnIndex = NULL;
 | 
						|
	}
 | 
						|
	if(NULL != m_pISTTagMetaByTableAndID)
 | 
						|
	{
 | 
						|
		m_pISTTagMetaByTableAndID->Release();
 | 
						|
		m_pISTTagMetaByTableAndID = NULL;
 | 
						|
	}
 | 
						|
	if(NULL != m_pISTTagMetaByTableAndName)
 | 
						|
	{
 | 
						|
		m_pISTTagMetaByTableAndName->Release();
 | 
						|
		m_pISTTagMetaByTableAndName = NULL;
 | 
						|
	}
 | 
						|
	if(NULL != m_pISTColumnMeta)
 | 
						|
	{
 | 
						|
		m_pISTColumnMeta->Release();
 | 
						|
		m_pISTColumnMeta = NULL;
 | 
						|
	}
 | 
						|
	if(NULL != m_pISTColumnMetaByTableAndID)
 | 
						|
	{
 | 
						|
		m_pISTColumnMetaByTableAndID->Release();
 | 
						|
		m_pISTColumnMetaByTableAndID = NULL;
 | 
						|
	}
 | 
						|
	if(NULL != m_pISTColumnMetaByTableAndName)
 | 
						|
	{
 | 
						|
		m_pISTColumnMetaByTableAndName->Release();
 | 
						|
		m_pISTColumnMetaByTableAndName = NULL;
 | 
						|
	}
 | 
						|
	if(NULL != m_pISTTableMetaForMetabaseTables)
 | 
						|
	{
 | 
						|
		m_pISTTableMetaForMetabaseTables->Release();
 | 
						|
		m_pISTTableMetaForMetabaseTables = NULL;
 | 
						|
	}
 | 
						|
	if(NULL != m_wszBinFileForMeta)
 | 
						|
	{
 | 
						|
		ReleaseBinFile(NULL,
 | 
						|
			           &m_wszBinFileForMeta);
 | 
						|
	}
 | 
						|
	if(NULL != m_wszIIS_MD_UT_SERVER)
 | 
						|
	{
 | 
						|
		delete [] m_wszIIS_MD_UT_SERVER;
 | 
						|
		m_wszIIS_MD_UT_SERVER           = NULL;
 | 
						|
	}
 | 
						|
	m_cchIIS_MD_UT_SERVER               = 0;
 | 
						|
	if(NULL != m_wszIIS_MD_UT_FILE)
 | 
						|
	{
 | 
						|
		delete [] m_wszIIS_MD_UT_FILE;
 | 
						|
		m_wszIIS_MD_UT_FILE             = NULL;
 | 
						|
	}
 | 
						|
	m_cchIIS_MD_UT_FILE                 = 0;
 | 
						|
	if(NULL != m_wszIIS_MD_UT_WAM)
 | 
						|
	{
 | 
						|
		delete [] m_wszIIS_MD_UT_WAM;
 | 
						|
		m_wszIIS_MD_UT_WAM              = NULL;
 | 
						|
	}
 | 
						|
	m_cchIIS_MD_UT_WAM                  = 0;
 | 
						|
	if(NULL != m_wszASP_MD_UT_APP)
 | 
						|
	{
 | 
						|
		delete [] m_wszASP_MD_UT_APP;
 | 
						|
		m_wszASP_MD_UT_APP              = NULL;
 | 
						|
	}
 | 
						|
	m_cchASP_MD_UT_APP                  = 0;
 | 
						|
 | 
						|
} // Destructor
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    Initializes the object with all the metatable ISTs that are needed during
 | 
						|
    write.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    [in]   Bool indicating if we should fail if the bin file is absent.
 | 
						|
           There are some scenarios in which we can tolerate this, and some
 | 
						|
           where we dont - hence the distinction.
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    HRESULT
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
HRESULT CWriterGlobalHelper::InitializeGlobals(BOOL i_bFailIfBinFileAbsent)
 | 
						|
{
 | 
						|
	ISimpleTableDispenser2*	pISTDisp      = NULL;
 | 
						|
	HRESULT                 hr            = S_OK;
 | 
						|
	STQueryCell				Query[2];
 | 
						|
	ULONG					cCell         = sizeof(Query)/sizeof(STQueryCell);
 | 
						|
	ULONG                   iStartRow     = 0;
 | 
						|
	DWORD					dwKeyTypeID   = MD_KEY_TYPE;
 | 
						|
	ULONG                   aColSearch [] = {iCOLUMNMETA_Table,
 | 
						|
		                                     iCOLUMNMETA_ID
 | 
						|
		                                    };
 | 
						|
	ULONG                   cColSearch    = sizeof(aColSearch)/sizeof(ULONG);
 | 
						|
	ULONG                   iRow          = 0;
 | 
						|
	ULONG                   iCol          = iMBProperty_Attributes;
 | 
						|
	LPVOID                  apvSearch[cCOLUMNMETA_NumberOfColumns];
 | 
						|
	ULONG                   aColSearchFlags[] = {iTAGMETA_Table,
 | 
						|
	                                             iTAGMETA_ColumnIndex
 | 
						|
	};
 | 
						|
	ULONG                   cColSearchFlags = sizeof(aColSearchFlags)/sizeof(ULONG);
 | 
						|
	LPVOID                  apvSearchFlags[cTAGMETA_NumberOfColumns];
 | 
						|
	apvSearchFlags[iTAGMETA_ColumnIndex] = (LPVOID)&iCol;
 | 
						|
 | 
						|
	//
 | 
						|
	// Save the bin file name
 | 
						|
	//
 | 
						|
 | 
						|
	hr = GetBinFile(NULL,
 | 
						|
					&m_wszBinFileForMeta);
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
		DBGINFOW((DBG_CONTEXT,
 | 
						|
				 L"[InitializeGlobals] Unable to get the the bin file name. GetBinFileName failed with hr = 0x%x.\n",
 | 
						|
				 hr));
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
	if(( i_bFailIfBinFileAbsent)  &&
 | 
						|
	   ((NULL == m_wszBinFileForMeta) || (0 == *m_wszBinFileForMeta))
 | 
						|
	  )
 | 
						|
	{
 | 
						|
		DBGINFOW((DBG_CONTEXT,
 | 
						|
				 L"[InitializeGlobals] Expected to find a valid schema bin file. GetBinFileName returned a null file name. Bin file is either invalid or not found.\n"));
 | 
						|
 | 
						|
		hr = HRESULT_FROM_WIN32(ERROR_FILE_INVALID);
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
	//
 | 
						|
	// Get the dispenser
 | 
						|
	//
 | 
						|
 | 
						|
	hr = GetSimpleTableDispenser (WSZ_PRODUCT_IIS, 0, &pISTDisp);
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
	//
 | 
						|
	// Initialize the in file name in the query.
 | 
						|
	//
 | 
						|
 | 
						|
	Query[0].pData     = (LPVOID)m_wszBinFileForMeta;
 | 
						|
    Query[0].eOperator = eST_OP_EQUAL;
 | 
						|
    Query[0].iCell     = iST_CELL_FILE;
 | 
						|
    Query[0].dbType    = DBTYPE_WSTR;
 | 
						|
    Query[0].cbSize    = m_cchBinFileForMeta*sizeof(WCHAR);
 | 
						|
 | 
						|
	//
 | 
						|
	// m_pISTTableMetaForMetabaseTables
 | 
						|
	// Save pointer to tablemeta for all tables in the metabase database.
 | 
						|
	// This is used for fetching tablemeta of a table from the metabase 
 | 
						|
	// database, given its internal name.
 | 
						|
	//
 | 
						|
 | 
						|
	DBGINFOW((DBG_CONTEXT,
 | 
						|
			  L"[InitializeGlobals] Reading table: %s with hint %s from file: %s.\n", 
 | 
						|
			  wszTABLE_COLUMNMETA,
 | 
						|
			  g_wszByID,
 | 
						|
              m_wszBinFileForMeta));
 | 
						|
 | 
						|
	Query[1].pData		= (void*)wszDATABASE_METABASE;
 | 
						|
	Query[1].eOperator	= eST_OP_EQUAL;
 | 
						|
	Query[1].iCell		= iTABLEMETA_Database;
 | 
						|
	Query[1].dbType		= DBTYPE_WSTR;
 | 
						|
	Query[1].cbSize		= 0;
 | 
						|
 | 
						|
	hr = pISTDisp->GetTable(wszDATABASE_META,
 | 
						|
							wszTABLE_TABLEMETA,
 | 
						|
							(LPVOID)Query,
 | 
						|
							(LPVOID)&cCell,
 | 
						|
							eST_QUERYFORMAT_CELLS,
 | 
						|
							0,
 | 
						|
							(LPVOID*)&m_pISTTableMetaForMetabaseTables);
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
	//
 | 
						|
	// Fetch the internal pointers to relevant table names. This is a perf
 | 
						|
	// optimization. When you use internal pointers to strings in 
 | 
						|
	// GetRowIndexBySearch, then you avoid a string compare
 | 
						|
	//
 | 
						|
 | 
						|
	hr = GetInternalTableName(pISTDisp,
 | 
						|
		                      wszTABLE_IIsConfigObject,
 | 
						|
							  &m_wszTABLE_IIsConfigObject);
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
	    //
 | 
						|
	    // TODO: Must we fail? We could log and ignore, it would 
 | 
						|
	    // just be slower.
 | 
						|
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
	hr = GetInternalTableName(pISTDisp,
 | 
						|
		                      wszTABLE_MBProperty,
 | 
						|
							  &m_wszTABLE_MBProperty);
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
	    //
 | 
						|
	    // TODO: Must we fail? We could log and ignore, it would 
 | 
						|
	    // just be slower.
 | 
						|
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
	
 | 
						|
	//
 | 
						|
	// m_pISTTagMetaByTableAndColumnIndexAndName
 | 
						|
	// Save pointer to TagMeta table with ByTableAndColumnIndexAndName index hint.
 | 
						|
	// This is used for fetching tagmeta of a tag, given its tagname, columnindex
 | 
						|
	// and table.
 | 
						|
	//
 | 
						|
 | 
						|
	DBGINFOW((DBG_CONTEXT,
 | 
						|
			  L"[InitializeGlobals] Reading table: %s with hint %s from file: %s.\n", 
 | 
						|
			  wszTABLE_TAGMETA,
 | 
						|
			  g_wszByTableAndColumnIndexAndNameOnly,
 | 
						|
              m_wszBinFileForMeta));
 | 
						|
 | 
						|
	Query[1].pData		= (void*)g_wszByTableAndColumnIndexAndNameOnly;
 | 
						|
	Query[1].eOperator	= eST_OP_EQUAL;
 | 
						|
	Query[1].iCell		= iST_CELL_INDEXHINT;
 | 
						|
	Query[1].dbType		= DBTYPE_WSTR;
 | 
						|
	Query[1].cbSize		= 0;
 | 
						|
 | 
						|
	hr = pISTDisp->GetTable(wszDATABASE_META,
 | 
						|
							wszTABLE_TAGMETA,
 | 
						|
							(LPVOID)Query,
 | 
						|
							(LPVOID)&cCell,
 | 
						|
							eST_QUERYFORMAT_CELLS,
 | 
						|
							0,
 | 
						|
							(LPVOID*)&m_pISTTagMetaByTableAndColumnIndexAndName);
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
	//
 | 
						|
	// m_pISTTagMetaByTableAndColumnIndexAndValue
 | 
						|
	// Save pointer to TagMeta table with ByTableAndColumnIndexAndValue index hint.
 | 
						|
	// This is used for fetching tagmeta of a tag, given its value, columnindex
 | 
						|
	// and table.
 | 
						|
	//
 | 
						|
 | 
						|
	DBGINFOW((DBG_CONTEXT,
 | 
						|
			  L"[InitializeGlobals] Reading table: %s with hint %s from file: %s.\n", 
 | 
						|
			  wszTABLE_TAGMETA,
 | 
						|
			  g_wszByTableAndColumnIndexAndValueOnly,
 | 
						|
              m_wszBinFileForMeta));
 | 
						|
 | 
						|
 | 
						|
	Query[1].pData		= (void*)g_wszByTableAndColumnIndexAndValueOnly;
 | 
						|
	Query[1].eOperator	= eST_OP_EQUAL;
 | 
						|
	Query[1].iCell		= iST_CELL_INDEXHINT;
 | 
						|
	Query[1].dbType		= DBTYPE_WSTR;
 | 
						|
	Query[1].cbSize		= 0;
 | 
						|
 | 
						|
	hr = pISTDisp->GetTable(wszDATABASE_META,
 | 
						|
							wszTABLE_TAGMETA,
 | 
						|
							(LPVOID)Query,
 | 
						|
							(LPVOID)&cCell,
 | 
						|
							eST_QUERYFORMAT_CELLS,
 | 
						|
							0,
 | 
						|
							(LPVOID*)&m_pISTTagMetaByTableAndColumnIndexAndValue);
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
	//
 | 
						|
	// m_pISTTagMetaByTableAndColumnIndex
 | 
						|
	// Save pointer to TagMeta table with ByTableAndColumnIndex index hint.
 | 
						|
	// This is used for fetching tagmeta for all tags of a column, given 
 | 
						|
	// columnindex and table.
 | 
						|
	//
 | 
						|
 | 
						|
	DBGINFOW((DBG_CONTEXT,
 | 
						|
			  L"[InitializeGlobals] Reading table: %s with hint %s from file: %s.\n", 
 | 
						|
			  wszTABLE_TAGMETA,
 | 
						|
			  g_wszByTableAndColumnIndexOnly,
 | 
						|
              m_wszBinFileForMeta));
 | 
						|
 | 
						|
 | 
						|
	Query[1].pData		= (void*)g_wszByTableAndColumnIndexOnly;
 | 
						|
	Query[1].eOperator	= eST_OP_EQUAL;
 | 
						|
	Query[1].iCell		= iST_CELL_INDEXHINT;
 | 
						|
	Query[1].dbType		= DBTYPE_WSTR;
 | 
						|
	Query[1].cbSize		= 0;
 | 
						|
 | 
						|
	hr = pISTDisp->GetTable(wszDATABASE_META,
 | 
						|
							wszTABLE_TAGMETA,
 | 
						|
							(LPVOID)Query,
 | 
						|
							(LPVOID)&cCell,
 | 
						|
							eST_QUERYFORMAT_CELLS,
 | 
						|
							0,
 | 
						|
							(LPVOID*)&m_pISTTagMetaByTableAndColumnIndex);
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
	//
 | 
						|
	// m_pISTTagMetaByTableAndID
 | 
						|
	// Save pointer to TagMeta table with ByTableAndColumnIndex index hint.
 | 
						|
	// This is used for fetching tagmeta for a tag, given the table and 
 | 
						|
	// metabase tag ID. The assumption here is that the tag ID is unique
 | 
						|
	// for every tag in a table.
 | 
						|
	//
 | 
						|
 | 
						|
	Query[1].pData		= (void*)g_wszByTableAndTagIDOnly;
 | 
						|
	Query[1].eOperator	= eST_OP_EQUAL;
 | 
						|
	Query[1].iCell		= iST_CELL_INDEXHINT;
 | 
						|
	Query[1].dbType		= DBTYPE_WSTR;
 | 
						|
	Query[1].cbSize		= 0;
 | 
						|
 | 
						|
	hr = pISTDisp->GetTable(wszDATABASE_META,
 | 
						|
							wszTABLE_TAGMETA,
 | 
						|
							(LPVOID)Query,
 | 
						|
							(LPVOID)&cCell,
 | 
						|
							eST_QUERYFORMAT_CELLS,
 | 
						|
							0,
 | 
						|
							(LPVOID*)&m_pISTTagMetaByTableAndID);
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
	//
 | 
						|
	// m_pISTTagMetaByTableAndName
 | 
						|
	// Save pointer to TagMeta table with ByTableAndTagName index hint.
 | 
						|
	// This is used for fetching tagmeta for a tag, given the table and
 | 
						|
	// tag name. The Asumption here is that the tagname is unique
 | 
						|
	// for every tag in a table.
 | 
						|
	//
 | 
						|
 | 
						|
	Query[1].pData		= (void*)g_wszByTableAndTagNameOnly;
 | 
						|
	Query[1].eOperator	= eST_OP_EQUAL;
 | 
						|
	Query[1].iCell		= iST_CELL_INDEXHINT;
 | 
						|
	Query[1].dbType		= DBTYPE_WSTR;
 | 
						|
	Query[1].cbSize		= 0;
 | 
						|
 | 
						|
	hr = pISTDisp->GetTable(wszDATABASE_META,
 | 
						|
							wszTABLE_TAGMETA,
 | 
						|
							(LPVOID)Query,
 | 
						|
							(LPVOID)&cCell,
 | 
						|
							eST_QUERYFORMAT_CELLS,
 | 
						|
							0,
 | 
						|
							(LPVOID*)&m_pISTTagMetaByTableAndName);
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
	//
 | 
						|
	// m_pISTColumnMeta
 | 
						|
	// This is used for:
 | 
						|
	// A. Fetching columnmeta of a given table - Using GetRowIndexByIndentity with table name, starting with index 0.
 | 
						|
	// B. Getting columnmeta of a given table + column index - Using GetRowIndexByIndentity with table name and index.
 | 
						|
	//
 | 
						|
 | 
						|
	cCell = cCell-1;
 | 
						|
 | 
						|
	hr = pISTDisp->GetTable(wszDATABASE_META,
 | 
						|
							wszTABLE_COLUMNMETA,
 | 
						|
							(LPVOID)Query,
 | 
						|
							(LPVOID)&cCell,
 | 
						|
							eST_QUERYFORMAT_CELLS,
 | 
						|
							0,
 | 
						|
							(LPVOID*)&m_pISTColumnMeta);
 | 
						|
 | 
						|
	cCell = cCell+1;
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
	//
 | 
						|
	// m_pISTColumnMetaByTableAndID
 | 
						|
	// Save pointer to ColumnMeta table with ByTableAndID index hint.
 | 
						|
	// This is used for fetching columnmeta of a column, given its metabase id.
 | 
						|
	//
 | 
						|
 | 
						|
	DBGINFOW((DBG_CONTEXT,
 | 
						|
			  L"[InitializeGlobals] Reading table: %s with hint %s from file: %s.\n", 
 | 
						|
			  wszTABLE_COLUMNMETA,
 | 
						|
			  g_wszByID,
 | 
						|
              m_wszBinFileForMeta));
 | 
						|
 | 
						|
	Query[1].pData		= (void*)g_wszByID;
 | 
						|
	Query[1].eOperator	= eST_OP_EQUAL;
 | 
						|
	Query[1].iCell		= iST_CELL_INDEXHINT;
 | 
						|
	Query[1].dbType		= DBTYPE_WSTR;
 | 
						|
	Query[1].cbSize		= 0;
 | 
						|
 | 
						|
	hr = pISTDisp->GetTable(wszDATABASE_META,
 | 
						|
							wszTABLE_COLUMNMETA,
 | 
						|
							(LPVOID)Query,
 | 
						|
							(LPVOID)&cCell,
 | 
						|
							eST_QUERYFORMAT_CELLS,
 | 
						|
							0,
 | 
						|
							(LPVOID*)&m_pISTColumnMetaByTableAndID);
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
	//
 | 
						|
	// m_pISTColumnMetaByTableAndName
 | 
						|
	// Save pointer to ColumnMeta table with ByTableAndName index hint.
 | 
						|
	// This is used for fetching columnmeta of a column, given its internal 
 | 
						|
	// name and the table to which it belongs.
 | 
						|
	//
 | 
						|
 | 
						|
	DBGINFOW((DBG_CONTEXT,
 | 
						|
			  L"[InitializeGlobals] Reading table: %s with hint %s from file: %s.\n", 
 | 
						|
			  wszTABLE_COLUMNMETA,
 | 
						|
			  g_wszByID,
 | 
						|
              m_wszBinFileForMeta));
 | 
						|
 | 
						|
	Query[1].pData		= (void*)g_wszByName;
 | 
						|
	Query[1].eOperator	= eST_OP_EQUAL;
 | 
						|
	Query[1].iCell		= iST_CELL_INDEXHINT;
 | 
						|
	Query[1].dbType		= DBTYPE_WSTR;
 | 
						|
	Query[1].cbSize		= 0;
 | 
						|
 | 
						|
	hr = pISTDisp->GetTable(wszDATABASE_META,
 | 
						|
							wszTABLE_COLUMNMETA,
 | 
						|
							(LPVOID)Query,
 | 
						|
							(LPVOID)&cCell,
 | 
						|
							eST_QUERYFORMAT_CELLS,
 | 
						|
							0,
 | 
						|
							(LPVOID*)&m_pISTColumnMetaByTableAndName);
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	//
 | 
						|
	// Save meta information about the KeyType property.
 | 
						|
	//
 | 
						|
 | 
						|
	apvSearch[iCOLUMNMETA_Table] = (LPVOID)m_wszTABLE_IIsConfigObject;
 | 
						|
	apvSearch[iCOLUMNMETA_ID] = (LPVOID)&dwKeyTypeID;
 | 
						|
 | 
						|
	hr = m_pISTColumnMetaByTableAndID->GetRowIndexBySearch(iStartRow, 
 | 
						|
		                                                   cColSearch, 
 | 
						|
											               aColSearch,
 | 
						|
											               NULL, 
 | 
						|
											               apvSearch,
 | 
						|
											               &iRow);
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	hr = m_pISTColumnMetaByTableAndID->GetColumnValues(iRow,
 | 
						|
		                                               m_cColKeyTypeMetaData,
 | 
						|
										               NULL,
 | 
						|
										               NULL,
 | 
						|
										               m_apvKeyTypeMetaData);
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
	//
 | 
						|
	// Save start row index in tagmeta table for the attributes column 
 | 
						|
	// in MBproperty table.
 | 
						|
	//
 | 
						|
 | 
						|
	apvSearchFlags[iTAGMETA_Table] = m_wszTABLE_MBProperty;
 | 
						|
 | 
						|
	hr = m_pISTTagMetaByTableAndColumnIndex->GetRowIndexBySearch(iStartRow, 
 | 
						|
												                 cColSearchFlags, 
 | 
						|
												                 aColSearchFlags,
 | 
						|
												                 NULL, 
 | 
						|
												                 apvSearchFlags,
 | 
						|
												                 (ULONG*)&m_iStartRowForAttributes);
 | 
						|
	
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
	    //
 | 
						|
	    // TODO: Must we fail? We could log and ignore, it would 
 | 
						|
	    // just be slower.
 | 
						|
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
exit:
 | 
						|
 | 
						|
	if(NULL != pISTDisp)
 | 
						|
	{
 | 
						|
		pISTDisp->Release();
 | 
						|
		pISTDisp = NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	return hr;
 | 
						|
 | 
						|
 | 
						|
	
 | 
						|
} // CWriterGlobalHelper::InitializeGlobals
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    This function gets pointers to the internal table names so that it can be 
 | 
						|
    used as part of queries later on. The advantage of getting an internal 
 | 
						|
    pointer is the fact that Stephen does a pointer comapare instead of
 | 
						|
    string compare.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    [in]   Dispenser
 | 
						|
    [in]   Table name
 | 
						|
    [out]  Internal pointer to table name
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    HRESULT
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
HRESULT CWriterGlobalHelper::GetInternalTableName(ISimpleTableDispenser2*  i_pISTDisp,
 | 
						|
												  LPCWSTR                  i_wszTableName,
 | 
						|
												  LPWSTR*                  o_wszInternalTableName)
 | 
						|
{
 | 
						|
	HRESULT               hr            = S_OK;
 | 
						|
	ULONG                 iCol          = iTABLEMETA_InternalName;
 | 
						|
	ULONG                 iRow          = 0;
 | 
						|
 | 
						|
	if(NULL == m_pISTTableMetaForMetabaseTables)
 | 
						|
	{
 | 
						|
		return E_INVALIDARG;
 | 
						|
	}
 | 
						|
 | 
						|
	DBGINFOW((DBG_CONTEXT,
 | 
						|
			  L"[GetInternalTableName] Reading table: %s from file: %s.\n", 
 | 
						|
			  wszTABLE_TABLEMETA,
 | 
						|
              m_wszBinFileForMeta));
 | 
						|
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
		return hr;
 | 
						|
	}
 | 
						|
 | 
						|
	hr = m_pISTTableMetaForMetabaseTables->GetRowIndexByIdentity(NULL,
 | 
						|
											                    (LPVOID*)&i_wszTableName,
 | 
						|
											                    &iRow);
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
		return hr;
 | 
						|
	}
 | 
						|
 | 
						|
	hr = m_pISTTableMetaForMetabaseTables->GetColumnValues(iRow,
 | 
						|
		                                                   1,
 | 
						|
										                   &iCol,
 | 
						|
										                   NULL,
 | 
						|
										                   (LPVOID*)o_wszInternalTableName);
 | 
						|
 | 
						|
	if(FAILED(hr))
 | 
						|
	{
 | 
						|
	    //
 | 
						|
	    // TODO: Must we fail? We could log and ignore, it would 
 | 
						|
	    // just be slower.
 | 
						|
 | 
						|
		return hr;
 | 
						|
	}
 | 
						|
 | 
						|
	return hr;
 | 
						|
 | 
						|
} // CWriterGlobalHelper::GetInternalTableName
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    This function converts a given flag value to its string representation.
 | 
						|
    The flags bits are delimited by | and if we encounter an unknown bit/bits
 | 
						|
    we just spit out a stringized ULONG.
 | 
						|
 | 
						|
    Eg: dwValue == 3  => ACCESS_READ | ACCESS_WRITE
 | 
						|
        dwValue == 88 => 88
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    [in]   flag numeric value
 | 
						|
    [out]  String representation for the flag
 | 
						|
    [in]  Meta table name to search for flag meta
 | 
						|
    [in]  Meta table column to search for flag meta
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    HRESULT
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
HRESULT CWriterGlobalHelper::FlagToString(DWORD      dwValue,
 | 
						|
								          LPWSTR*    pwszData,
 | 
						|
									      LPWSTR     wszTable,
 | 
						|
									      ULONG      iColFlag)
 | 
						|
{
 | 
						|
 | 
						|
	DWORD	dwAllFlags = 0;
 | 
						|
	HRESULT hr         = S_OK;
 | 
						|
	ULONG   iStartRow  = 0;
 | 
						|
	ULONG   iRow       = 0;
 | 
						|
	ULONG   iCol       = 0;
 | 
						|
	LPWSTR	wszFlag	   = NULL;
 | 
						|
 | 
						|
	ULONG   aCol[]     = {iTAGMETA_Value,
 | 
						|
					      iTAGMETA_InternalName,
 | 
						|
						  iTAGMETA_Table,
 | 
						|
						  iTAGMETA_ColumnIndex
 | 
						|
				         };
 | 
						|
	ULONG   cCol       = sizeof(aCol)/sizeof(ULONG);
 | 
						|
	LPVOID  apv[cTAGMETA_NumberOfColumns];
 | 
						|
	ULONG   cch        = 0;
 | 
						|
	LPVOID  apvIdentity [] = {(LPVOID)wszTable,
 | 
						|
							  (LPVOID)&iColFlag
 | 
						|
	};
 | 
						|
	ULONG   iColFlagMask = iCOLUMNMETA_FlagMask;
 | 
						|
	DWORD*  pdwFlagMask = NULL;
 | 
						|
 | 
						|
	DWORD   dwZero = 0;
 | 
						|
	ULONG   aColSearchByValue[] = {iTAGMETA_Table,
 | 
						|
							       iTAGMETA_ColumnIndex,
 | 
						|
							       iTAGMETA_Value
 | 
						|
	};
 | 
						|
	ULONG   cColSearchByValue = sizeof(aColSearchByValue)/sizeof(ULONG);
 | 
						|
	LPVOID  apvSearchByValue[cTAGMETA_NumberOfColumns];
 | 
						|
	apvSearchByValue[iTAGMETA_Table]       = (LPVOID)wszTable;
 | 
						|
	apvSearchByValue[iTAGMETA_ColumnIndex] = (LPVOID)&iColFlag;
 | 
						|
	apvSearchByValue[iTAGMETA_Value]       = (LPVOID)&dwZero;
 | 
						|
 | 
						|
 | 
						|
	//
 | 
						|
	// Make one pass and compute all flag values for this property.
 | 
						|
	//
 | 
						|
 | 
						|
	hr = m_pISTColumnMeta->GetRowIndexByIdentity(NULL,
 | 
						|
		                                         apvIdentity,
 | 
						|
								 			     &iRow);
 | 
						|
 | 
						|
	if(SUCCEEDED(hr))
 | 
						|
	{
 | 
						|
		hr = m_pISTColumnMeta->GetColumnValues(iRow,
 | 
						|
											   1,
 | 
						|
											   &iColFlagMask,
 | 
						|
											   NULL,
 | 
						|
											   (LPVOID*)&pdwFlagMask);
 | 
						|
 | 
						|
		if(FAILED(hr))
 | 
						|
		{
 | 
						|
			return hr;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	else if(E_ST_NOMOREROWS != hr)
 | 
						|
	{
 | 
						|
		return hr;
 | 
						|
	}
 | 
						|
 | 
						|
	if((E_ST_NOMOREROWS == hr) || 
 | 
						|
	   (0 != (dwValue & (~(dwValue & (*pdwFlagMask))))))
 | 
						|
	{
 | 
						|
		//
 | 
						|
		//	There was no mask associated with this property, or there are one
 | 
						|
		//  or more unknown bits set. Spit out a regular number.
 | 
						|
		//
 | 
						|
 | 
						|
		return UnsignedLongToNewString(dwValue,
 | 
						|
		                               pwszData);
 | 
						|
 | 
						|
	}
 | 
						|
	else if(0 == dwValue)
 | 
						|
	{
 | 
						|
		//
 | 
						|
		// See if there is a flag with 0 as its value.
 | 
						|
		//
 | 
						|
 | 
						|
		hr = m_pISTTagMetaByTableAndColumnIndexAndValue->GetRowIndexBySearch(iStartRow, 
 | 
						|
																	         cColSearchByValue, 
 | 
						|
																			 aColSearchByValue,
 | 
						|
																			 NULL, 
 | 
						|
																			 apvSearchByValue,
 | 
						|
																			 &iRow);
 | 
						|
 | 
						|
		if(E_ST_NOMOREROWS == hr)
 | 
						|
		{
 | 
						|
			//
 | 
						|
			// There was no flag associated with the value zero. Spit out a 
 | 
						|
			// regular number
 | 
						|
			//
 | 
						|
 | 
						|
		    return UnsignedLongToNewString(dwValue,
 | 
						|
		                                   pwszData);
 | 
						|
 | 
						|
		}
 | 
						|
		else if(FAILED(hr))
 | 
						|
		{
 | 
						|
			return hr;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			iCol = iTAGMETA_InternalName;
 | 
						|
 | 
						|
			hr = m_pISTTagMetaByTableAndColumnIndexAndValue->GetColumnValues(iRow,
 | 
						|
																		     1,
 | 
						|
																			 &iCol,
 | 
						|
																			 NULL,
 | 
						|
																			 (LPVOID*)&wszFlag);
 | 
						|
			if(FAILED(hr))
 | 
						|
			{
 | 
						|
				return hr;
 | 
						|
			}
 | 
						|
 | 
						|
            return StringToNewString(wszFlag,
 | 
						|
				                     wcslen(wszFlag),
 | 
						|
			                         pwszData);
 | 
						|
 | 
						|
		}
 | 
						|
	}
 | 
						|
	else 
 | 
						|
	{
 | 
						|
		//
 | 
						|
		// Make another pass, and convert flag to string.
 | 
						|
		//
 | 
						|
 | 
						|
		ULONG  cchMaxFlagString  = MAX_FLAG_STRING_CHARS;
 | 
						|
		LPWSTR wszExtension      = L" | ";
 | 
						|
		ULONG  cchExtension      = wcslen(wszExtension);
 | 
						|
		ULONG  cchFlagStringUsed = 0;
 | 
						|
 | 
						|
        hr = NewString(cchMaxFlagString,
 | 
						|
		               pwszData);
 | 
						|
 | 
						|
		if(FAILED(hr))
 | 
						|
		{
 | 
						|
            return hr;
 | 
						|
		}
 | 
						|
		
 | 
						|
		hr = GetStartRowIndex(wszTable,
 | 
						|
			                  iColFlag,
 | 
						|
							  &iStartRow);
 | 
						|
 | 
						|
		if(FAILED(hr) || (iStartRow == -1))
 | 
						|
		{
 | 
						|
			return hr;
 | 
						|
		}
 | 
						|
 | 
						|
		for(iRow=iStartRow;;iRow++)
 | 
						|
		{
 | 
						|
			hr = m_pISTTagMetaByTableAndColumnIndex->GetColumnValues(iRow,
 | 
						|
												                     cCol,
 | 
						|
															         aCol,
 | 
						|
															         NULL,
 | 
						|
															         apv);
 | 
						|
			if((dwValue  == 0)         ||
 | 
						|
			   (E_ST_NOMOREROWS == hr) ||
 | 
						|
			   (iColFlag != *(DWORD*)apv[iTAGMETA_ColumnIndex]) ||
 | 
						|
			   (0 != wcscmp(wszTable, (LPWSTR)apv[iTAGMETA_Table])) // OK to do case sensitive compare because all callers pass well known table names
 | 
						|
			  )
 | 
						|
			{
 | 
						|
				hr = S_OK;
 | 
						|
				break;
 | 
						|
			}
 | 
						|
			else if(FAILED(hr))
 | 
						|
			{
 | 
						|
				return hr;
 | 
						|
			}
 | 
						|
 | 
						|
			if(0 != (dwValue & (*(DWORD*)apv[iTAGMETA_Value])))
 | 
						|
			{
 | 
						|
				ULONG strlen = wcslen((LPWSTR)apv[iTAGMETA_InternalName]);
 | 
						|
 | 
						|
				if(cchFlagStringUsed + cchExtension + strlen > cchMaxFlagString)
 | 
						|
				{
 | 
						|
				    hr = ReAllocateString(MAX_FLAG_STRING_CHARS + cchExtension + strlen,
 | 
						|
					                      &cchMaxFlagString,
 | 
						|
					                      pwszData);
 | 
						|
 | 
						|
					if(FAILED(hr))
 | 
						|
					{
 | 
						|
						return hr;
 | 
						|
					}
 | 
						|
 | 
						|
				}
 | 
						|
 | 
						|
				if(**pwszData != 0)
 | 
						|
				{
 | 
						|
					wcscat(*pwszData, wszExtension);
 | 
						|
					cchFlagStringUsed = cchFlagStringUsed + cchExtension;
 | 
						|
				}
 | 
						|
 | 
						|
				wcscat(*pwszData, (LPWSTR)apv[iTAGMETA_InternalName]);
 | 
						|
				cchFlagStringUsed = cchFlagStringUsed + strlen;
 | 
						|
 | 
						|
                //
 | 
						|
				// Clear out that bit
 | 
						|
				//
 | 
						|
 | 
						|
				dwValue = dwValue & (~(*(DWORD*)apv[iTAGMETA_Value]));
 | 
						|
			}
 | 
						|
 | 
						|
		} // End for
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	return S_OK;
 | 
						|
 | 
						|
} // CWriterGlobalHelper::FlagToString
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    This function converts a given enum value to its string representation.
 | 
						|
    If we encounter an unknown bit/bits we just spit out a stringized ULONG.
 | 
						|
 | 
						|
    Eg: dwValue == 101  => IIS_MD_UT_SERVER
 | 
						|
        dwValue == 88 => 88
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    [in]   Enum numeric value
 | 
						|
    [out]  String representation for the flag
 | 
						|
    [in]  Meta table name to search for flag meta
 | 
						|
    [in]  Meta table column to search for flag meta
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    HRESULT
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
HRESULT CWriterGlobalHelper::EnumToString(DWORD      dwValue,
 | 
						|
								          LPWSTR*    pwszData,
 | 
						|
									      LPWSTR     wszTable,
 | 
						|
									      ULONG      iColEnum)
 | 
						|
{
 | 
						|
 | 
						|
	HRESULT hr             = S_OK;
 | 
						|
	ULONG   iStartRow      = 0;
 | 
						|
	ULONG   iRow           = 0;
 | 
						|
	ULONG   iColEnumString = iTAGMETA_InternalName;
 | 
						|
	LPWSTR  wszEnum        = NULL;
 | 
						|
	ULONG   aColSearch[]   = {iTAGMETA_Table,
 | 
						|
		                      iTAGMETA_ColumnIndex,
 | 
						|
							  iTAGMETA_Value};
 | 
						|
	ULONG   cColSearch     = sizeof(aColSearch)/sizeof(ULONG);
 | 
						|
	LPVOID  apvSearch[cTAGMETA_NumberOfColumns];
 | 
						|
    apvSearch[iTAGMETA_Table]       = (LPVOID)wszTable;
 | 
						|
    apvSearch[iTAGMETA_ColumnIndex] = (LPVOID)&iColEnum;
 | 
						|
	apvSearch[iTAGMETA_Value]       = (LPVOID)&dwValue;
 | 
						|
	
 | 
						|
 | 
						|
	hr = m_pISTTagMetaByTableAndColumnIndexAndValue->GetRowIndexBySearch(iStartRow,
 | 
						|
		                                                                 cColSearch,
 | 
						|
		                                                                 aColSearch,
 | 
						|
		                                                                 NULL,
 | 
						|
		                                                                 apvSearch,
 | 
						|
		                                                                 &iRow);
 | 
						|
 | 
						|
	if(E_ST_NOMOREROWS == hr)
 | 
						|
	{
 | 
						|
		//
 | 
						|
		// Convert to a number
 | 
						|
		//
 | 
						|
		WCHAR	wszBufferDW[20];
 | 
						|
		_ultow(dwValue, wszBufferDW, 10);
 | 
						|
		*pwszData = new WCHAR[wcslen(wszBufferDW)+1];
 | 
						|
		if(NULL == *pwszData)
 | 
						|
		{
 | 
						|
			return E_OUTOFMEMORY;
 | 
						|
		}
 | 
						|
		wcscpy(*pwszData, wszBufferDW);
 | 
						|
		return S_OK;
 | 
						|
 | 
						|
	}
 | 
						|
	else if(FAILED(hr))
 | 
						|
	{
 | 
						|
		return hr;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		hr = m_pISTTagMetaByTableAndColumnIndexAndValue->GetColumnValues(iRow,
 | 
						|
														                 1,
 | 
						|
														                 &iColEnumString,
 | 
						|
														                 NULL,
 | 
						|
														                 (LPVOID*)&wszEnum);
 | 
						|
		if(FAILED(hr))
 | 
						|
		{
 | 
						|
			return hr;
 | 
						|
		}
 | 
						|
 | 
						|
		*pwszData = new WCHAR[wcslen(wszEnum)+1];
 | 
						|
		if(NULL == *pwszData)
 | 
						|
		{
 | 
						|
			return E_OUTOFMEMORY;
 | 
						|
		}
 | 
						|
		wcscpy(*pwszData, wszEnum);
 | 
						|
	}
 | 
						|
 | 
						|
	return S_OK;
 | 
						|
 | 
						|
} // CWiterGlobalHelper::EnumToString
 | 
						|
 | 
						|
  
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    This function converts a given data value to its string representation,
 | 
						|
    taking into account the type of the data.   
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    [in]   Pointer to data
 | 
						|
    [in]   Count of bytes of data
 | 
						|
    [in]   Metabase id of the property
 | 
						|
    [in]   Type of the property
 | 
						|
    [in]   Attibutes of the property
 | 
						|
    [out]  String representation of the value. 
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    HRESULT
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
HRESULT CWriterGlobalHelper::ToString(PBYTE   pbData,
 | 
						|
								      DWORD   cbData,
 | 
						|
								      DWORD   dwIdentifier,
 | 
						|
								      DWORD   dwDataType,
 | 
						|
								      DWORD   dwAttributes,
 | 
						|
								      LPWSTR* pwszData)
 | 
						|
{
 | 
						|
	HRESULT hr              = S_OK;
 | 
						|
	ULONG	i				= 0;
 | 
						|
	ULONG	j				= 0;
 | 
						|
	WCHAR*	wszTemp			= NULL;
 | 
						|
	BYTE*	a_Bytes			= NULL;
 | 
						|
	WCHAR*	wszMultisz      = NULL;
 | 
						|
	ULONG   cMultisz        = 0;
 | 
						|
	ULONG   cchMultisz      = 0;
 | 
						|
	ULONG   cchBuffer       = 0;
 | 
						|
	ULONG   cchSubsz        = 0;
 | 
						|
	DWORD	dwValue			= 0;
 | 
						|
	WCHAR	wszBufferDW[40];
 | 
						|
	WCHAR	wszBufferDWTemp[40];
 | 
						|
	
 | 
						|
	ULONG   aColSearch[]    = {iCOLUMNMETA_Table,
 | 
						|
							   iCOLUMNMETA_ID
 | 
						|
						      };
 | 
						|
	ULONG   cColSearch      = sizeof(aColSearch)/sizeof(ULONG);
 | 
						|
	LPVOID  apvSearch[cCOLUMNMETA_NumberOfColumns];
 | 
						|
	apvSearch[iCOLUMNMETA_Table] = (LPVOID)m_wszTABLE_IIsConfigObject;
 | 
						|
	apvSearch[iCOLUMNMETA_ID] = (LPVOID)&dwIdentifier; 
 | 
						|
 | 
						|
	ULONG   iRow            = 0;
 | 
						|
	ULONG   iStartRow       = 0;
 | 
						|
	LPWSTR  wszEscaped      = NULL;
 | 
						|
	ULONG   cchEscaped      = 0;
 | 
						|
	BOOL    bEscaped        = FALSE;
 | 
						|
 | 
						|
	*pwszData = NULL;
 | 
						|
 | 
						|
	if(NULL == pbData)	
 | 
						|
	{
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
 | 
						|
	if(IsSecureMetadata(dwIdentifier, dwAttributes))
 | 
						|
	{
 | 
						|
		dwDataType = BINARY_METADATA;
 | 
						|
	}
 | 
						|
 | 
						|
	switch(dwDataType)
 | 
						|
	{
 | 
						|
		case BINARY_METADATA:
 | 
						|
 | 
						|
            //
 | 
						|
			// Each byte is represented by 2 chars. 
 | 
						|
			//
 | 
						|
 | 
						|
			hr  = NewString(cbData*2,
 | 
						|
			                pwszData);
 | 
						|
 | 
						|
			if(FAILED(hr))
 | 
						|
			{
 | 
						|
				goto exit;
 | 
						|
			}
 | 
						|
 | 
						|
			wszTemp			= *pwszData;
 | 
						|
			a_Bytes			= (BYTE*)(pbData);
 | 
						|
 | 
						|
			for(i=0; i<cbData; i++)
 | 
						|
			{
 | 
						|
                wszTemp[0] = kByteToWchar[a_Bytes[i]][0];
 | 
						|
                wszTemp[1] = kByteToWchar[a_Bytes[i]][1];
 | 
						|
                wszTemp += 2;
 | 
						|
			}
 | 
						|
 | 
						|
			*wszTemp	= 0; // Add the terminating NULL
 | 
						|
 | 
						|
			break;
 | 
						|
 | 
						|
		case DWORD_METADATA :
 | 
						|
 | 
						|
			//
 | 
						|
			// TODO: After Stephen supports hex, convert these to hex.
 | 
						|
			//
 | 
						|
 | 
						|
			dwValue = *(DWORD*)(pbData);
 | 
						|
 | 
						|
			//
 | 
						|
			// First check to see if it is a flag or bool type.
 | 
						|
			//
 | 
						|
 | 
						|
			hr = m_pISTColumnMetaByTableAndID->GetRowIndexBySearch(iStartRow, 
 | 
						|
													               cColSearch, 
 | 
						|
													               aColSearch,
 | 
						|
													               NULL, 
 | 
						|
													               apvSearch,
 | 
						|
													               &iRow);
 | 
						|
 | 
						|
			if(SUCCEEDED(hr))
 | 
						|
			{
 | 
						|
			    ULONG  aCol [] = {iCOLUMNMETA_Index,
 | 
						|
				                 iCOLUMNMETA_MetaFlags
 | 
						|
							    };
 | 
						|
				ULONG  cCol = sizeof(aCol)/sizeof(ULONG);
 | 
						|
				LPVOID apv[cCOLUMNMETA_NumberOfColumns];
 | 
						|
 | 
						|
				hr = m_pISTColumnMetaByTableAndID->GetColumnValues(iRow,
 | 
						|
									                               cCol,
 | 
						|
													               aCol,
 | 
						|
													               NULL,
 | 
						|
													               apv);
 | 
						|
 | 
						|
				if(FAILED(hr))
 | 
						|
				{
 | 
						|
					goto exit;
 | 
						|
				}
 | 
						|
				
 | 
						|
				if(0 != (fCOLUMNMETA_FLAG & (*(DWORD*)apv[iCOLUMNMETA_MetaFlags])))
 | 
						|
				{
 | 
						|
					//
 | 
						|
					// This is a flag property convert it.
 | 
						|
					//
 | 
						|
 | 
						|
					hr = FlagToString(dwValue,
 | 
						|
								      pwszData,
 | 
						|
								      m_wszTABLE_IIsConfigObject,
 | 
						|
							          *(ULONG*)apv[iCOLUMNMETA_Index]);
 | 
						|
	
 | 
						|
					goto exit;
 | 
						|
				}
 | 
						|
				else if(0 != (fCOLUMNMETA_BOOL & (*(DWORD*)apv[iCOLUMNMETA_MetaFlags])))
 | 
						|
				{
 | 
						|
					//
 | 
						|
					// This is a bool property
 | 
						|
					//
 | 
						|
 | 
						|
					hr = BoolToString(dwValue,
 | 
						|
					                  pwszData);
 | 
						|
 | 
						|
					goto exit;
 | 
						|
				}
 | 
						|
				
 | 
						|
			}
 | 
						|
			else if((E_ST_NOMOREROWS != hr) && FAILED(hr))
 | 
						|
			{
 | 
						|
				goto exit;
 | 
						|
			}
 | 
						|
 | 
						|
			hr = UnsignedLongToNewString(dwValue,
 | 
						|
			                             pwszData);
 | 
						|
 | 
						|
			if(FAILED(hr))
 | 
						|
			{
 | 
						|
			    goto exit;
 | 
						|
			}
 | 
						|
 | 
						|
			break;
 | 
						|
 | 
						|
		case MULTISZ_METADATA :
 | 
						|
 | 
						|
			//
 | 
						|
			// Count the number of multisz
 | 
						|
			//
 | 
						|
 | 
						|
			wszMultisz = (WCHAR*)(pbData);
 | 
						|
			cchSubsz   = wcslen(wszMultisz);
 | 
						|
 | 
						|
			hr = EscapeString(wszMultisz,
 | 
						|
				              cchSubsz,
 | 
						|
							  &bEscaped,
 | 
						|
							  &wszEscaped,
 | 
						|
							  &cchEscaped);
 | 
						|
 | 
						|
			if(FAILED(hr))
 | 
						|
			{
 | 
						|
				goto exit;
 | 
						|
			}
 | 
						|
 | 
						|
			cMultisz++;
 | 
						|
			cchMultisz = cchMultisz + cchEscaped;
 | 
						|
			wszMultisz = wszMultisz + cchSubsz + 1;
 | 
						|
 | 
						|
			while((0 != *wszMultisz) && ((BYTE*)wszMultisz < (pbData + cbData)))			
 | 
						|
			{
 | 
						|
 | 
						|
				if(bEscaped && (NULL != wszEscaped))	// reset for next string in multisz
 | 
						|
				{
 | 
						|
					delete [] wszEscaped;
 | 
						|
					wszEscaped = NULL;
 | 
						|
					bEscaped = FALSE;
 | 
						|
				}
 | 
						|
 | 
						|
			    cchSubsz   = wcslen(wszMultisz);
 | 
						|
 | 
						|
				hr = EscapeString(wszMultisz,
 | 
						|
					              cchSubsz,
 | 
						|
								  &bEscaped,
 | 
						|
								  &wszEscaped,
 | 
						|
								  &cchEscaped);
 | 
						|
 | 
						|
				if(FAILED(hr))
 | 
						|
				{
 | 
						|
					goto exit;
 | 
						|
				}
 | 
						|
 | 
						|
				cMultisz++;
 | 
						|
				cchMultisz = cchMultisz + cchEscaped;
 | 
						|
				wszMultisz = wszMultisz + cchSubsz + 1;
 | 
						|
			}
 | 
						|
 | 
						|
			cchBuffer = cchMultisz + (5*(cMultisz-1)) + 1;    // (5*(cMultisz-1) => \r\n\t\t\t. 
 | 
						|
 | 
						|
			//
 | 
						|
			// Allocate new string
 | 
						|
			//
 | 
						|
 | 
						|
            hr = NewString(cchBuffer,
 | 
						|
			               pwszData);
 | 
						|
 | 
						|
			if(FAILED(hr))
 | 
						|
			{
 | 
						|
			    goto exit;
 | 
						|
			}
 | 
						|
 | 
						|
			//
 | 
						|
			// Create the string
 | 
						|
			//
 | 
						|
 | 
						|
			wszMultisz = (WCHAR*)(pbData);
 | 
						|
		    cchSubsz   = wcslen(wszMultisz);
 | 
						|
			wszTemp = *pwszData;
 | 
						|
 | 
						|
			hr = EscapeString(wszMultisz,
 | 
						|
				              cchSubsz,
 | 
						|
							  &bEscaped,
 | 
						|
							  &wszEscaped,
 | 
						|
							  &cchEscaped);
 | 
						|
 | 
						|
			if(FAILED(hr))
 | 
						|
			{
 | 
						|
				goto exit;
 | 
						|
			}
 | 
						|
 | 
						|
//			wcscat(wszTemp, wszEscaped);
 | 
						|
			memcpy(wszTemp, wszEscaped, (cchEscaped*sizeof(WCHAR)));
 | 
						|
			wszTemp = wszTemp + cchEscaped;
 | 
						|
			*wszTemp = L'\0';
 | 
						|
			wszMultisz = wszMultisz + cchSubsz + 1;
 | 
						|
 | 
						|
			while((0 != *wszMultisz) && ((BYTE*)wszMultisz < (pbData + cbData)))			
 | 
						|
			{
 | 
						|
//				wcscat(wszTemp, L"\r\n\t\t\t");
 | 
						|
				memcpy(wszTemp, g_wszMultiszSeperator, (g_cchMultiszSeperator*sizeof(WCHAR)));
 | 
						|
				wszTemp = wszTemp + g_cchMultiszSeperator;
 | 
						|
				*wszTemp = L'\0';
 | 
						|
 | 
						|
				if(bEscaped && (NULL != wszEscaped))	// reset for next string in multisz
 | 
						|
				{
 | 
						|
					delete [] wszEscaped;
 | 
						|
					wszEscaped = NULL;
 | 
						|
					bEscaped = FALSE;
 | 
						|
				}
 | 
						|
 | 
						|
			    cchSubsz   = wcslen(wszMultisz);
 | 
						|
 | 
						|
				hr = EscapeString(wszMultisz,
 | 
						|
					              cchSubsz,
 | 
						|
								  &bEscaped,
 | 
						|
								  &wszEscaped,
 | 
						|
								  &cchEscaped);
 | 
						|
 | 
						|
				if(FAILED(hr))
 | 
						|
				{
 | 
						|
					goto exit;
 | 
						|
				}
 | 
						|
 | 
						|
//				wcscat(wszTemp, wszEscaped);
 | 
						|
				memcpy(wszTemp, wszEscaped, (cchEscaped*sizeof(WCHAR)));
 | 
						|
				wszTemp = wszTemp + cchEscaped;
 | 
						|
				*wszTemp = L'\0';
 | 
						|
				wszMultisz = wszMultisz + cchSubsz + 1;
 | 
						|
			}
 | 
						|
 | 
						|
			break;
 | 
						|
 | 
						|
		case EXPANDSZ_METADATA :
 | 
						|
		case STRING_METADATA :
 | 
						|
 | 
						|
			hr = EscapeString((WCHAR*)pbData,
 | 
						|
				              wcslen((WCHAR*)pbData),
 | 
						|
							  &bEscaped,
 | 
						|
							  &wszEscaped,
 | 
						|
							  &cchEscaped);
 | 
						|
 | 
						|
			if(FAILED(hr))
 | 
						|
			{
 | 
						|
				goto exit;
 | 
						|
			}
 | 
						|
 | 
						|
            hr = StringToNewString(wszEscaped,
 | 
						|
				                   cchEscaped,
 | 
						|
			                       pwszData);
 | 
						|
 | 
						|
			if(FAILED(hr))
 | 
						|
			{
 | 
						|
				goto exit;
 | 
						|
			}
 | 
						|
 | 
						|
			break;
 | 
						|
 | 
						|
		default:
 | 
						|
			DBGINFOW((DBG_CONTEXT,
 | 
						|
					  L"[ToString] Unknown data type %d for ID: %d.\n", 
 | 
						|
					  dwDataType,
 | 
						|
					  dwIdentifier));
 | 
						|
			hr = E_INVALIDARG;
 | 
						|
			break;
 | 
						|
			
 | 
						|
	}
 | 
						|
 | 
						|
exit:
 | 
						|
 | 
						|
	if(bEscaped && (NULL != wszEscaped))
 | 
						|
	{
 | 
						|
		delete [] wszEscaped;
 | 
						|
		wszEscaped = NULL;
 | 
						|
		bEscaped = FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	return hr;
 | 
						|
 | 
						|
} // CWriterGlobalHelper::ToString
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    This function converts a given boolean its string representation,
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    [in]   Bool value
 | 
						|
    [out]  String representation of the Bool. 
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    HRESULT
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
HRESULT CWriterGlobalHelper::BoolToString(DWORD      dwValue,
 | 
						|
                                          LPWSTR*    pwszData)
 | 
						|
{
 | 
						|
	HRESULT hr = S_OK;
 | 
						|
 | 
						|
	if(dwValue)
 | 
						|
	{
 | 
						|
	    hr = StringToNewString(g_wszTrue,
 | 
						|
			                   g_cchTrue,
 | 
						|
		                       pwszData);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    hr = StringToNewString(g_wszFalse,
 | 
						|
			                   g_cchFalse,
 | 
						|
		                       pwszData);
 | 
						|
	}
 | 
						|
 | 
						|
	return hr;
 | 
						|
 | 
						|
} // CWriterGlobalHelper::BoolToString
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    Helper funciton that return the start row index in the metatable for
 | 
						|
    the flag concerned
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    [in]   Table to which the flag property belongs
 | 
						|
    [in]   Column index of the flag property
 | 
						|
    [out]  Start row index of the flag meta in the metatable for this flag.
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    HRESULT
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
HRESULT CWriterGlobalHelper::GetStartRowIndex(LPWSTR    wszTable,
 | 
						|
			                                  ULONG     iColFlag,
 | 
						|
							                  ULONG*    piStartRow)
 | 
						|
{
 | 
						|
	HRESULT hr = S_OK;
 | 
						|
	ULONG   aColSearch[] = {iTAGMETA_Table,
 | 
						|
	                        iTAGMETA_ColumnIndex
 | 
						|
						   };
 | 
						|
	ULONG   cColSearch = sizeof(aColSearch)/sizeof(ULONG);
 | 
						|
	LPVOID  apvSearch[cTAGMETA_NumberOfColumns];
 | 
						|
	apvSearch[iTAGMETA_Table] = (LPVOID)wszTable;
 | 
						|
	apvSearch[iTAGMETA_ColumnIndex] = (LPVOID)&iColFlag;
 | 
						|
 | 
						|
	*piStartRow = 0;
 | 
						|
 | 
						|
	if((0 == wcscmp(wszTable, m_wszTABLE_MBProperty)) && // OK to do case sensitive compare because all callers pass well known table names
 | 
						|
	   (iMBProperty_Attributes == iColFlag))
 | 
						|
	{
 | 
						|
		*piStartRow = m_iStartRowForAttributes;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		hr = m_pISTTagMetaByTableAndColumnIndex->GetRowIndexBySearch(*piStartRow, 
 | 
						|
															         cColSearch, 
 | 
						|
															         aColSearch,
 | 
						|
															         NULL, 
 | 
						|
															         apvSearch,
 | 
						|
														             piStartRow);
 | 
						|
 | 
						|
		if(E_ST_NOMOREROWS == hr)
 | 
						|
		{
 | 
						|
			hr = S_OK;
 | 
						|
			*piStartRow = -1;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return hr;
 | 
						|
 | 
						|
} // CWriterGlobalHelper::GetStartRowIndex
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    Function that escapes a string according to the following ruules:
 | 
						|
 | 
						|
    ************************************************************************
 | 
						|
    ESCAPING LEGAL XML
 | 
						|
    ************************************************************************
 | 
						|
 | 
						|
    Following characters are legal in XML:
 | 
						|
    #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | 
 | 
						|
    [#x10000-#x10FFFF] 
 | 
						|
 | 
						|
    Out of this legal set, following need special escaping:
 | 
						|
    Quote         => " => 34 => Escaped as: "	
 | 
						|
    Ampersand     => & => 38 => Escaped as: &	
 | 
						|
    Less than     => < => 60 => Escaped as: <
 | 
						|
    Gretater than => > => 62 => Escaped as: >
 | 
						|
 | 
						|
    Note there may be chars in the legal set that may appear legal in certain 
 | 
						|
	languages and not in others. All such chars are not escaped. We could 
 | 
						|
	escape them as hex numbers Eg 0xA as 
, but we do not want to 
 | 
						|
	do this because editors may be able to render these chars, when we change 
 | 
						|
	the language.
 | 
						|
    Following are the hex values of such chars.
 | 
						|
 | 
						|
    #x9 | #xA | #xD | [#x7F-#xD7FF] | [#xE000-#xFFFD]
 | 
						|
 | 
						|
    Note we disregard the range [#x10000-#x10FFFF] because it is not 2 bytes
 | 
						|
 | 
						|
    ************************************************************************
 | 
						|
    ESCAPING ILLEGAL XML
 | 
						|
    ************************************************************************
 | 
						|
 | 
						|
    Illegal XML is also escaped in the following manner
 | 
						|
 | 
						|
    We add 0x10000 to the char value and escape it as hex. the XML 
 | 
						|
    interceptor will render these chars correctly. Note that we are using
 | 
						|
    the fact unicode chars are not > 0x10000 and hence we can make this 
 | 
						|
    assumption.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    [in]   String to be escaped
 | 
						|
	[in]   Count of characters in the string
 | 
						|
    [out]  Bool indicating if escaping happened
 | 
						|
    [out]  Escaped string - If no escaping occured, it will just point to
 | 
						|
           the original string. If escaping occured it will point to a newly
 | 
						|
           allocated string that the caller needs to free. The caller can 
 | 
						|
           use the bool to determine what action he needs to take.
 | 
						|
	[out]  Count of characters in the escaped string
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    HRESULT
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
HRESULT CWriterGlobalHelper::EscapeString(LPCWSTR wszString,
 | 
						|
			                              ULONG   cchString,
 | 
						|
                                          BOOL*   pbEscaped,
 | 
						|
									      LPWSTR* pwszEscaped,
 | 
						|
										  ULONG*  pcchEscaped)
 | 
						|
{
 | 
						|
 | 
						|
	ULONG              cchAdditional        = 0;
 | 
						|
	HRESULT            hr                   = S_OK;
 | 
						|
	WORD               wChar                = 0;
 | 
						|
    eESCAPE            eEscapeType          = eNoESCAPE;
 | 
						|
	const ULONG        cchLegalCharAsHex    = (sizeof(WCHAR)*2) + 4; // Each byte is represented as 2 WCHARs plus 4 additional escape chars (&#x;)
 | 
						|
	WCHAR              wszLegalCharAsHex[cchLegalCharAsHex];			
 | 
						|
	const ULONG        cchIllegalCharAsHex  = cchLegalCharAsHex + 1; // illegal xml has an extra char because we are adding 0x10000 to it.
 | 
						|
	WCHAR              wszIllegalCharAsHex[cchIllegalCharAsHex];		
 | 
						|
	DWORD              dwIllegalChar        = 0;
 | 
						|
	static WCHAR       wszQuote[]           = L""";
 | 
						|
	static const ULONG  cchQuote            = (sizeof(wszQuote)/sizeof(WCHAR))-1;
 | 
						|
	static WCHAR       wszAmp[]             = L"&";
 | 
						|
	static const ULONG  cchAmp              = (sizeof(wszAmp)/sizeof(WCHAR))-1;
 | 
						|
	static WCHAR       wszlt[]              = L"<";
 | 
						|
	static const ULONG  cchlt               = (sizeof(wszlt)/sizeof(WCHAR))-1;
 | 
						|
	static WCHAR       wszgt[]              = L">";
 | 
						|
	static const ULONG  cchgt               = (sizeof(wszgt)/sizeof(WCHAR))-1;
 | 
						|
 | 
						|
	*pbEscaped = FALSE;
 | 
						|
 | 
						|
	//
 | 
						|
	// Go through each char and compute the addtional chars needed to escape
 | 
						|
	//
 | 
						|
 | 
						|
	for(ULONG i=0; i<cchString; i++)
 | 
						|
	{
 | 
						|
		eEscapeType = GetEscapeType(wszString[i]);
 | 
						|
 | 
						|
		switch(eEscapeType)
 | 
						|
		{
 | 
						|
		case eNoESCAPE:
 | 
						|
			break;
 | 
						|
		case eESCAPEgt:
 | 
						|
			cchAdditional = cchAdditional + cchgt;
 | 
						|
			*pbEscaped = TRUE;
 | 
						|
			break;
 | 
						|
		case eESCAPElt:
 | 
						|
			cchAdditional = cchAdditional + cchlt;
 | 
						|
			*pbEscaped = TRUE;
 | 
						|
			break;
 | 
						|
		case eESCAPEquote:
 | 
						|
			cchAdditional = cchAdditional + cchQuote;
 | 
						|
			*pbEscaped = TRUE;
 | 
						|
			break;
 | 
						|
		case eESCAPEamp:
 | 
						|
			cchAdditional = cchAdditional + cchAmp;
 | 
						|
			*pbEscaped = TRUE;
 | 
						|
			break;
 | 
						|
		case eESCAPEashex:
 | 
						|
			cchAdditional = cchAdditional + cchLegalCharAsHex;
 | 
						|
			*pbEscaped = TRUE;
 | 
						|
			break;
 | 
						|
		case eESCAPEillegalxml:
 | 
						|
			cchAdditional = cchAdditional + cchIllegalCharAsHex;
 | 
						|
			*pbEscaped = TRUE;
 | 
						|
			break;
 | 
						|
		default:
 | 
						|
			return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if(*pbEscaped)
 | 
						|
	{
 | 
						|
		//
 | 
						|
		// String needs to be escaped, allocate the extra memory
 | 
						|
		//
 | 
						|
 | 
						|
        hr = NewString(cchString+cchAdditional,
 | 
						|
		               pwszEscaped);
 | 
						|
 | 
						|
		if(FAILED(hr))
 | 
						|
		{
 | 
						|
		    return hr;
 | 
						|
		}
 | 
						|
 | 
						|
		*pcchEscaped = cchString+cchAdditional;
 | 
						|
 | 
						|
		//
 | 
						|
		// Escape string
 | 
						|
		//
 | 
						|
 | 
						|
		for(ULONG i=0; i<cchString; i++)
 | 
						|
		{
 | 
						|
			eEscapeType = GetEscapeType(wszString[i]);
 | 
						|
 | 
						|
			switch(eEscapeType)
 | 
						|
			{
 | 
						|
			case eNoESCAPE:
 | 
						|
			    wcsncat(*pwszEscaped, (WCHAR*)&(wszString[i]), 1);
 | 
						|
				break;
 | 
						|
			case eESCAPEgt:
 | 
						|
			    wcsncat(*pwszEscaped, wszgt, cchgt);
 | 
						|
				break;
 | 
						|
			case eESCAPElt:
 | 
						|
			    wcsncat(*pwszEscaped, wszlt, cchlt);
 | 
						|
				break;
 | 
						|
			case eESCAPEquote:
 | 
						|
			    wcsncat(*pwszEscaped, wszQuote, cchQuote);
 | 
						|
				break;
 | 
						|
			case eESCAPEamp:
 | 
						|
			    wcsncat(*pwszEscaped, wszAmp, cchAmp);
 | 
						|
				break;
 | 
						|
			case eESCAPEashex:
 | 
						|
				_snwprintf(wszLegalCharAsHex, cchLegalCharAsHex, L"&#x%04hX;", wszString[i]);
 | 
						|
				wcsncat(*pwszEscaped, (WCHAR*)wszLegalCharAsHex, cchLegalCharAsHex);
 | 
						|
				break;
 | 
						|
			case eESCAPEillegalxml:
 | 
						|
				dwIllegalChar = 0x10000 + wszString[i];
 | 
						|
				_snwprintf(wszIllegalCharAsHex, cchIllegalCharAsHex, L"&#x%05X;", dwIllegalChar);
 | 
						|
				wcsncat(*pwszEscaped, (WCHAR*)wszIllegalCharAsHex, cchIllegalCharAsHex);
 | 
						|
				break;
 | 
						|
			default:
 | 
						|
				return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
 | 
						|
				break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		//
 | 
						|
		// String need not be escaped, just pass the string out.
 | 
						|
		//
 | 
						|
 | 
						|
		*pwszEscaped = (LPWSTR)wszString;
 | 
						|
		*pcchEscaped = cchString;
 | 
						|
	}
 | 
						|
 | 
						|
	return S_OK;
 | 
						|
 | 
						|
} // CWriterGlobalHelper::EscapeString
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    Returns the escape type of a character
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    [in]   Char
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    Escape type
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
eESCAPE CWriterGlobalHelper::GetEscapeType(WCHAR i_wChar)
 | 
						|
{
 | 
						|
	WORD    wChar       = i_wChar;
 | 
						|
	eESCAPE eEscapeType = eNoESCAPE;
 | 
						|
 | 
						|
	if(wChar <= 0xFF)
 | 
						|
	{
 | 
						|
		eEscapeType = kWcharToEscape[wChar];
 | 
						|
	}
 | 
						|
	else if( (wChar <= 0xD7FF) ||
 | 
						|
		     ((wChar >= 0xE000) && (wChar <= 0xFFFD))
 | 
						|
		   )
 | 
						|
	{
 | 
						|
		eEscapeType = eNoESCAPE;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		eEscapeType = eESCAPEillegalxml;
 | 
						|
	}
 | 
						|
 | 
						|
	return eEscapeType;
 | 
						|
 | 
						|
} // CWriterGlobalHelper::GetEscapeType
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    Returns the user type
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    [in]   user type
 | 
						|
	[out]  user type
 | 
						|
	[out]  count of chars in user type
 | 
						|
	[out]  alloced or not
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    HRESULT
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
HRESULT CWriterGlobalHelper::GetUserType(DWORD   i_dwUserType,
 | 
						|
				                         LPWSTR* o_pwszUserType,
 | 
						|
										 ULONG*  o_cchUserType,
 | 
						|
										 BOOL*   o_bAllocedUserType)
 | 
						|
{
 | 
						|
	HRESULT hr            = S_OK;
 | 
						|
	DWORD	iColUserType  = iCOLUMNMETA_UserType;
 | 
						|
 | 
						|
	*o_bAllocedUserType = FALSE;
 | 
						|
 | 
						|
	switch(i_dwUserType)
 | 
						|
	{
 | 
						|
 | 
						|
	case IIS_MD_UT_SERVER:
 | 
						|
 | 
						|
		if(NULL == m_wszIIS_MD_UT_SERVER)
 | 
						|
		{
 | 
						|
			hr = EnumToString(i_dwUserType,
 | 
						|
				              &m_wszIIS_MD_UT_SERVER,
 | 
						|
				              wszTABLE_COLUMNMETA,
 | 
						|
				              iColUserType);
 | 
						|
			if(FAILED(hr))
 | 
						|
			{
 | 
						|
				return hr;
 | 
						|
			}
 | 
						|
 | 
						|
			m_cchIIS_MD_UT_SERVER = wcslen(m_wszIIS_MD_UT_SERVER);
 | 
						|
		}
 | 
						|
 | 
						|
		*o_pwszUserType = m_wszIIS_MD_UT_SERVER;
 | 
						|
		*o_cchUserType  = m_cchIIS_MD_UT_SERVER;
 | 
						|
 | 
						|
		break;
 | 
						|
 | 
						|
	case IIS_MD_UT_FILE:
 | 
						|
 | 
						|
		if(NULL == m_wszIIS_MD_UT_FILE)
 | 
						|
		{
 | 
						|
			hr = EnumToString(i_dwUserType,
 | 
						|
				              &m_wszIIS_MD_UT_FILE,
 | 
						|
				              wszTABLE_COLUMNMETA,
 | 
						|
				              iColUserType);
 | 
						|
			if(FAILED(hr))
 | 
						|
			{
 | 
						|
				return hr;
 | 
						|
			}
 | 
						|
 | 
						|
			m_cchIIS_MD_UT_FILE = wcslen(m_wszIIS_MD_UT_FILE);
 | 
						|
		}
 | 
						|
 | 
						|
		*o_pwszUserType = m_wszIIS_MD_UT_FILE;
 | 
						|
		*o_cchUserType  = m_cchIIS_MD_UT_FILE;
 | 
						|
 | 
						|
		break;
 | 
						|
 | 
						|
	case IIS_MD_UT_WAM:
 | 
						|
 | 
						|
		if(NULL == m_wszIIS_MD_UT_WAM)
 | 
						|
		{
 | 
						|
			hr = EnumToString(i_dwUserType,
 | 
						|
				              &m_wszIIS_MD_UT_WAM,
 | 
						|
				              wszTABLE_COLUMNMETA,
 | 
						|
				              iColUserType);
 | 
						|
			if(FAILED(hr))
 | 
						|
			{
 | 
						|
				return hr;
 | 
						|
			}
 | 
						|
 | 
						|
			m_cchIIS_MD_UT_WAM = wcslen(m_wszIIS_MD_UT_WAM);
 | 
						|
		}
 | 
						|
 | 
						|
		*o_pwszUserType = m_wszIIS_MD_UT_WAM;
 | 
						|
		*o_cchUserType  = m_cchIIS_MD_UT_WAM;
 | 
						|
 | 
						|
		break;
 | 
						|
 | 
						|
	case ASP_MD_UT_APP:
 | 
						|
 | 
						|
		if(NULL == m_wszASP_MD_UT_APP)
 | 
						|
		{
 | 
						|
			hr = EnumToString(i_dwUserType,
 | 
						|
				              &m_wszASP_MD_UT_APP,
 | 
						|
				              wszTABLE_COLUMNMETA,
 | 
						|
				              iColUserType);
 | 
						|
			if(FAILED(hr))
 | 
						|
			{
 | 
						|
				return hr;
 | 
						|
			}
 | 
						|
 | 
						|
			m_cchASP_MD_UT_APP = wcslen(m_wszASP_MD_UT_APP);
 | 
						|
		}
 | 
						|
 | 
						|
		*o_pwszUserType = m_wszASP_MD_UT_APP;
 | 
						|
		*o_cchUserType  = m_cchASP_MD_UT_APP;
 | 
						|
 | 
						|
		break;
 | 
						|
 | 
						|
	default:
 | 
						|
 | 
						|
		hr = EnumToString(i_dwUserType,
 | 
						|
				          o_pwszUserType,
 | 
						|
			              wszTABLE_COLUMNMETA,
 | 
						|
				          iColUserType);
 | 
						|
		if(FAILED(hr))
 | 
						|
		{
 | 
						|
			return hr;
 | 
						|
		}
 | 
						|
 | 
						|
		*o_cchUserType = wcslen(*o_pwszUserType);
 | 
						|
		*o_bAllocedUserType = TRUE;
 | 
						|
 | 
						|
		break;
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	return S_OK;
 | 
						|
 | 
						|
} // CWriterGlobalHelper::GetUserType
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    Given the property id this routine contructs the name. If the name is not
 | 
						|
	found in the schema, it creates a name of the form Unknown_XXXX where XXX
 | 
						|
	is the ID.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    [in]   property id
 | 
						|
	[out]  name
 | 
						|
	[out]  alloced or not
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    HRESULT
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
HRESULT CWriterGlobalHelper::GetPropertyName(ULONG      i_dwPropertyID,
 | 
						|
											 LPWSTR*    o_wszName,
 | 
						|
											 BOOL*      o_bAlloced)
 | 
						|
{
 | 
						|
	HRESULT             hr                = S_OK;
 | 
						|
	ULONG               iStartRow         = 0;
 | 
						|
	ULONG               iRow              = 0;
 | 
						|
	ULONG               iColColumnMeta    = iCOLUMNMETA_InternalName;
 | 
						|
	LPWSTR              wszUnknownName    = NULL;
 | 
						|
	LPWSTR              wszColumnName     = NULL;
 | 
						|
	ULONG               aColSearchName[]  = {iCOLUMNMETA_Table,
 | 
						|
		                                     iCOLUMNMETA_ID
 | 
						|
		                                    };
 | 
						|
	ULONG               cColSearchName    = sizeof(aColSearchName)/sizeof(ULONG);
 | 
						|
	LPVOID              apvSearchName[cCOLUMNMETA_NumberOfColumns];
 | 
						|
 | 
						|
	apvSearchName[iCOLUMNMETA_Table]      = (LPVOID)m_wszTABLE_IIsConfigObject;
 | 
						|
	apvSearchName[iCOLUMNMETA_ID]         = (LPVOID)&i_dwPropertyID;
 | 
						|
 | 
						|
	*o_wszName = NULL;
 | 
						|
	*o_bAlloced = FALSE;
 | 
						|
 | 
						|
	//
 | 
						|
	// Fetch the Name for this ID
 | 
						|
	//
 | 
						|
 | 
						|
	hr = m_pISTColumnMetaByTableAndID->GetRowIndexBySearch(iStartRow, 
 | 
						|
													       cColSearchName, 
 | 
						|
													       aColSearchName,
 | 
						|
		 										           NULL, 
 | 
						|
														   apvSearchName,
 | 
						|
														   &iRow);
 | 
						|
 | 
						|
	if(E_ST_NOMOREROWS == hr)
 | 
						|
	{
 | 
						|
		hr  = CreateUnknownName(i_dwPropertyID,
 | 
						|
								&wszUnknownName);
 | 
						|
 | 
						|
		if(FAILED(hr))
 | 
						|
		{
 | 
						|
			goto exit;
 | 
						|
		}
 | 
						|
 | 
						|
		*o_wszName = wszUnknownName;
 | 
						|
		*o_bAlloced = TRUE;
 | 
						|
 | 
						|
	}
 | 
						|
	else if(FAILED(hr))
 | 
						|
	{
 | 
						|
		goto exit;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		hr = m_pISTColumnMetaByTableAndID->GetColumnValues(iRow,
 | 
						|
												           1,
 | 
						|
														   &iColColumnMeta,
 | 
						|
														   NULL,
 | 
						|
														  (LPVOID*)&wszColumnName);
 | 
						|
 | 
						|
		if(E_ST_NOMOREROWS == hr)
 | 
						|
		{
 | 
						|
			hr  = CreateUnknownName(i_dwPropertyID,
 | 
						|
									&wszUnknownName);
 | 
						|
 | 
						|
			if(FAILED(hr))
 | 
						|
			{
 | 
						|
				goto exit;
 | 
						|
			}
 | 
						|
 | 
						|
			*o_wszName = wszUnknownName;
 | 
						|
			*o_bAlloced = TRUE;
 | 
						|
 | 
						|
		}
 | 
						|
		else if(FAILED(hr))
 | 
						|
		{
 | 
						|
			goto exit;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			*o_wszName = wszColumnName;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
exit:
 | 
						|
 | 
						|
	if(FAILED(hr) && (NULL != wszUnknownName))
 | 
						|
	{
 | 
						|
		delete [] wszUnknownName;
 | 
						|
		wszUnknownName = NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	return hr;
 | 
						|
 | 
						|
}  // CWriterGlobalHelper::GetPropertyName
 | 
						|
 | 
						|
 | 
						|
/***************************************************************************++
 | 
						|
Routine Description:
 | 
						|
 | 
						|
    This function is invoked when the name for a given property is missing.
 | 
						|
    We create a name of the follwoing form: Unknown_NameXXXX
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
    [in]  ID
 | 
						|
    [out] Name
 | 
						|
 | 
						|
Return Value:
 | 
						|
 | 
						|
    HRESULT
 | 
						|
 | 
						|
--***************************************************************************/
 | 
						|
HRESULT CWriterGlobalHelper::CreateUnknownName(DWORD    dwID,
 | 
						|
										   LPWSTR*	pwszUnknownName)
 | 
						|
{
 | 
						|
	WCHAR wszID[40];
 | 
						|
	ULONG cchID = 0;
 | 
						|
	WCHAR* wszEnd = NULL;
 | 
						|
 | 
						|
	_ultow(dwID, wszID, 10);
 | 
						|
 | 
						|
	cchID = wcslen(wszID);
 | 
						|
 | 
						|
	*pwszUnknownName = new WCHAR[cchID+g_cchUnknownName+1];
 | 
						|
	if(NULL == *pwszUnknownName)
 | 
						|
    {
 | 
						|
		return E_OUTOFMEMORY;
 | 
						|
    }
 | 
						|
 | 
						|
	wszEnd = *pwszUnknownName;
 | 
						|
	memcpy(wszEnd, g_wszUnknownName, ((g_cchUnknownName+1)*sizeof(WCHAR)));
 | 
						|
	wszEnd = wszEnd + g_cchUnknownName;
 | 
						|
	memcpy(wszEnd, wszID, ((cchID+1)*sizeof(WCHAR)));
 | 
						|
 | 
						|
	return S_OK;
 | 
						|
 | 
						|
} // CWriterGlobalHelper::CreateUnknownName
 |