Sinkutil.cpp (Post-Categorizer)
Sinkutil.cpp
Important This sample code may not fully verify that strings passed to it are in fact null-terminated, nor that the referenced string buffers are large enough to store the generated contents. Your production code should always verify the validity and size of data passed as null-terminated strings before using, copying or adding to them. Using more-safe versions of the standard C string-handling functions is also recommended.
//------------------------------------------------------------
//
// File: Sinkutil.cpp
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-------------------------------------------------------------
#include "stdafx.h"
#include "SinkUtil.h"
#include "crtdbg.h"
#include "stdio.h"
#include "windows.h"
#include "string.h"
//-------------------------------------------------------------
//
// Function: ConvertStringtoCLSID
//
// Synopsis: Utility function to convert a string to a GUID. Uses CLSIDFromString
//
// Arguments:
// [in]
// LPSTR pszString,
//
// [out]
// LPGUID pguid)
//
// Returns:
// S_OK if the function succeeded
//
//-------------------------------------------------------------
HRESULT ConvertStringtoCLSID(
LPSTR pszString,
LPGUID pguid)
{
#define GUID_STRING_SIZE 39
HRESULT hr= S_OK;
WCHAR szWGuid[GUID_STRING_SIZE];
LPSTR pszSrc;
LPWSTR pszWDest;
PCFunctEnterEx((LPARAM)0, "ConvertStringtoCLSID");
if(pszString == NULL) {
hr = E_INVALIDARG;
goto CLEANUP;
}
pszSrc = pszString;
if(*pszSrc != '{') {
PCDebugTraceEx((LPARAM)0,"GUID should start with '{'");
hr = E_INVALIDARG;
goto CLEANUP;
}
// Convert to Unicode while you are copying to your temporary buffer.
// Do not worry about non-ANSI characters; this is a GUID string.
pszWDest = szWGuid;
while((*pszSrc) && (*pszSrc != '}') &&
(pszWDest < &szWGuid[GUID_STRING_SIZE - 2])) {
*pszWDest++ = *pszSrc++;
}
// On success, pszSrc will point to '}' (the last character of the GUID string).
if(*pszSrc != '}') {
PCDebugTraceEx((LPARAM)0,"End of GUID not found");
hr = E_INVALIDARG;
goto CLEANUP;
}
// pszDest will still be in range and have two chars left thanks
// to the condition in the preceding while loop.
*pszWDest++ = '}';
*pszWDest = '\0';
// Borrow the functionality of CLSIDFromString to get the 16-byte
// GUID from the GUID string.
hr = CLSIDFromString(
szWGuid,
pguid);
CLEANUP:
PCDebugTraceEx((LPARAM)0, "result %08lx", hr);
PCFunctLeaveEx((LPARAM)0);
return hr;
}
//------------------------------------------------------------
//
// Function: ShowMessage
//
// Synopsis: Utility function to display string in the debugger
//
// Arguments:
// [in]
// LPTSTR szMessage,
// ... - variable argument list
//
// Returns:
// S_OK if the function succeeded
//
//------------------------------------------------------------
BOOL ShowMessage(
LPTSTR szMessage, ...)
{
BOOL fRet = TRUE;
LPSTR pszErrorMessage = NULL;
BOOL fFormatMessage = FALSE;
TCHAR szBuffer[1024];
LPTSTR psz;
va_list ap;
va_start(ap, szMessage);
if(vswprintf_s (szBuffer, ARRAYSIZE(szBuffer), szMessage, ap) <=
0)
{
goto CLEANUP;
}
_ASSERT(lstrlen(szBuffer) + 1 < sizeof(szBuffer));
psz = szBuffer + lstrlen(szBuffer);
if(*psz != '\n')
{ // Append a CRLF
*psz++ = '\r';
*psz++ = '\n';
*psz = '\0';
}
OutputDebugString(szBuffer); \
CLEANUP:
return fRet;
}
//------------------------------------------------------------
//
// Function: CAttrEntry::operator new
//
// Synopsis: Operator overload new function to set the attribute name and GUID easily
//
// Arguments:
//
// size_t - [in] passed in sizeof CAttrEntry
// pszName - [in] Name of attribute
// pszGuid - [in] Stringised GUID
//
// Returns:
// pMem if allocation is successful; otherwise returns NULL
//
//-------------------------------------------------------------
void * CAttrEntry::operator new(size_t size, TCHAR * pszName, TCHAR * pszGuid)
{
HRESULT hr = S_OK;
CAttrEntry * pAttrTemp = NULL;
BYTE * pMem = new BYTE[size + lstrlen(pszName)+1];
if(!pMem) {
hr = E_OUTOFMEMORY;
goto CLEANUP;
}
pAttrTemp = (CAttrEntry *) pMem;
pAttrTemp->m_pszAttrName = (TCHAR *) (pMem + size);
strcpy_s(pAttrTemp->m_pszAttrName,size,pszName);
hr = ConvertStringtoCLSID(
pszGuid,
&(pAttrTemp->m_gGuid));
if (FAILED(hr))
goto CLEANUP;
CLEANUP:
if (FAILED(hr)) {
if (pMem) {
delete [] pMem;
pMem = NULL;
}
}
return (PVOID) pMem;
}
//------------------------------------------------------------
//
// Function: CAttrEntry::operator delete
//
// Synopsis: Operator overload delete function
//
// Arguments:
//
// size_t - [in] passed in sizeof CAttrEntry
// p - [in] Pointer to Memory
//
//
//
//-------------------------------------------------------------
void CAttrEntry::operator delete(void *pMem, size_t size)
{
delete [] (PBYTE) pMem;
}
//------------------------------------------------------------
//
// Function: CAttrList::AddEntry
//
// Synopsis: Linklist utility to add entries to a list
//
// Arguments:
//
// pszName - [in] Name of attribute
// pszGuid - [in] Stringised GUID
//
// Returns:
// S_OK if successful
//
//-------------------------------------------------------------
HRESULT CAttrList::AddEntry(TCHAR * pszName, TCHAR * pszGuid)
{
HRESULT hr = S_OK;
CAttrEntry * pNewEntry;
pNewEntry = new (pszName, pszGuid) CAttrEntry();
if(!pNewEntry) {
hr = E_OUTOFMEMORY;
goto CLEANUP;
}
if(m_pHead == NULL)
m_pHead = m_pTail = pNewEntry;
else {
m_pTail->m_pNext = pNewEntry;
m_pTail = pNewEntry;
m_pTail->m_pNext = NULL;
}
m_dwEntries++;
CLEANUP:
return hr;
}
//------------------------------------------------------------
//
// Function: HrReadRegParams
//
// Synopsis: Reads the same registry keys set for the CatReader and CatReadex Sinks
// Reads Clients attributes from registry. It then maintains a list
// of them.
// The following is the format in which the client must add attributes to the
// registry. Customers who use this sink must create and associate a new GUID for
// each required attribute. Both the GUID and attribute names are of the REG_SZ type.
//
// [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\CatReader]
// "officeLocation"="{8C515674-E27B-4924-95BD-7CB0FB24D9B1}"
// "sAMAccountType"="{AC515674-E27B-4924-95BD-7CB0FB24D9B2}"
//
//
// Arguments:
// CAttrList *pAttrList - The Link List
//
// Returns:
// S_OK if successful
//
//------------------------------------------------------------
HRESULT HrReadRegParams(CAttrList * pAttrList)
{
#define MAX_ATTR_SIZE 256
#define MAX_GUID_SIZE 40
HRESULT hr = S_OK;
LONG lError = 0;
HKEY hKey = NULL;
TCHAR szBuffer[MAX_ATTR_SIZE] ;
TCHAR szGuid[MAX_GUID_SIZE];
DWORD dwSize = MAX_ATTR_SIZE ;
DWORD dwIndex = 0;
DWORD dwType = 0;
DWORD dwcbGuid = MAX_GUID_SIZE;
PCFunctEnter("HrReadRegParams");
lError = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
PC_REGKEY_PATH,
0,
KEY_READ,
&hKey);
hr = HRESULT_FROM_WIN32(lError);
if(FAILED(hr)) {
PCErrorTraceEx((LPARAM)0, "Unable to open RegKey %s",
PC_REGKEY_PATH);
goto CLEANUP;
}
// Enumerate all values of the key.
// When there are no more values, it should return ERROR_NO_MORE_ITEMS.
lError = RegEnumValue(hKey,
dwIndex,
szBuffer,
&dwSize,
NULL,
&dwType,
(LPBYTE) szGuid,
&dwcbGuid);
hr = HRESULT_FROM_WIN32(lError);
while ( SUCCEEDED(hr) ) {
if(dwType == REG_SZ) {
PCDebugTraceEx((LPARAM)0, "Found Attribute %s Guid %s",
szBuffer, szGuid);
hr = pAttrList->AddEntry(szBuffer, szGuid);
if(FAILED(hr))
goto CLEANUP;
}
else {
// There might be other good registry keys.
PCDebugTraceEx((LPARAM)0, "Reg Value %s Not String Type",
szBuffer);
}
dwIndex++;
dwSize = MAX_ATTR_SIZE;
dwcbGuid = MAX_GUID_SIZE;
lError = RegEnumValue(hKey,
dwIndex,
szBuffer,
&dwSize,
NULL,
&dwType,
(LPBYTE) szGuid,
&dwcbGuid);
hr = HRESULT_FROM_WIN32(lError);
}
if(hr == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS))
hr = S_OK;
if(FAILED(hr)) {
PCErrorTraceEx((LPARAM)0, "Reading registry failed. Initialization failed.");
goto CLEANUP;
}
//
// Attributes were found.
//
if ( pAttrList->ListCount() > 0 ) {
hr = S_OK;
}
else {
hr = E_FAIL;
PCErrorTraceEx((LPARAM)0, "No attributes were found in the registry.");
goto CLEANUP;
}
CLEANUP:
if(hKey != NULL)
RegCloseKey(hKey);
PCDebugTraceEx((LPARAM)0, "result %08lx", hr);
PCDebugTraceEx((LPARAM)0, "returning S_OK", hr);
PCFunctLeave();
return hr;
}