|
|
//****************************************************************************
//
// Module: ULS.DLL
// File: utils.cpp
// Content: Miscellaneous utility functions and classes
//
// Copyright (c) Microsoft Corporation 1996-1997
//
//****************************************************************************
#include "ulsp.h"
//****************************************************************************
// HRESULT
// SetLPTSTR (LPTSTR *ppszName, LPCTSTR pszUserName)
//
// Purpose: Clone the provided string into a newly allocated buffer.
//
// Parameters:
// ppszName The buffer to receive a newly allocated string buffer.
// pszUserName The provided name string.
//
// Return Value:
// S_OK success if the string can be cloned.
// ILS_E_MEMORY if the string cannot be cloned.
//****************************************************************************
HRESULT SetLPTSTR (LPTSTR *ppszName, LPCTSTR pszUserName) { HRESULT hr;
TCHAR *pszNew = My_strdup (pszUserName); if (pszNew != NULL) { // Free the old name
//
::MemFree (*ppszName); *ppszName = pszNew; hr = S_OK; } else { hr = ILS_E_MEMORY; }
return hr; }
//****************************************************************************
// HRESULT
// SafeSetLPTSTR (LPTSTR *ppszName, LPCTSTR pszUserName)
//
// Purpose: Clone the provided string into a newly allocated buffer.
// It is ok that the provided string is NULL.
//
// Parameters:
// ppszName The buffer to receive a newly allocated string buffer.
// pszUserName The provided name string.
//
// Return Value:
// S_OK success if the string can be cloned.
// ILS_E_MEMORY if the non-null string cannot be cloned.
//****************************************************************************
HRESULT SafeSetLPTSTR (LPTSTR *ppszName, LPCTSTR pszUserName) { if (pszUserName == NULL) { MemFree (*ppszName); *ppszName = NULL; return S_FALSE; }
return SetLPTSTR (ppszName, pszUserName); }
//****************************************************************************
// HRESULT
// SetOffsetString ( TCHAR **ppszDst, BYTE *pSrcBase, ULONG uSrcOffset )
//
// Purpose: Clone the provided string into a newly allocated buffer.
// If the source string is null or empty, the destination string
// will be null.
//
// Parameters:
//
// Return Value:
// S_OK success if the string can be cloned.
// S_FALSE the destination string is null
// ILS_E_MEMORY if the string cannot be cloned.
//****************************************************************************
HRESULT SetOffsetString ( TCHAR **ppszDst, BYTE *pSrcBase, ULONG uSrcOffset ) { HRESULT hr = S_FALSE; TCHAR *pszNew = NULL;
if (uSrcOffset != INVALID_OFFSET) { TCHAR *pszSrc = (TCHAR *) (pSrcBase + uSrcOffset); if (*pszSrc != TEXT ('\0')) { pszNew = My_strdup (pszSrc); hr = (pszNew != NULL) ? S_OK : ILS_E_MEMORY; } }
if (SUCCEEDED (hr)) { ::MemFree (*ppszDst); *ppszDst = pszNew; }
return hr; }
//****************************************************************************
// HRESULT
// LPTSTR_to_BSTR (BSTR *pbstr, LPCTSTR psz)
//
// Purpose: Make a BSTR string from an LPTSTR string
//
// Parameters:
// pbstr The buffer to receive a newly allocated BSTR string.
// psz The LPTSTR string.
//
// Return Value:
// S_OK success if the string can be cloned.
// ILS_E_FAIL cannot convert the string to BSTR
// ILS_E_MEMORY cannot allocate enough memory for the BSTR string.
//****************************************************************************
HRESULT LPTSTR_to_BSTR (BSTR *pbstr, LPCTSTR psz) { #ifndef _UNICODE
BSTR bstr; int i; HRESULT hr;
// compute the length of the required BSTR
//
i = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0); if (i <= 0) { return ILS_E_FAIL; };
// allocate the widestr, +1 for terminating null
//
bstr = SysAllocStringLen(NULL, i-1); // SysAllocStringLen adds 1
if (bstr != NULL) { MultiByteToWideChar(CP_ACP, 0, psz, -1, (LPWSTR)bstr, i); ((LPWSTR)bstr)[i - 1] = 0; *pbstr = bstr; hr = S_OK; } else { hr = ILS_E_MEMORY; }; return hr;
#else
BSTR bstr;
bstr = SysAllocString(psz);
if (bstr != NULL) { *pbstr = bstr; return S_OK; } else { return ILS_E_MEMORY; };
#endif // _UNICODE
}
//****************************************************************************
// HRESULT
// BSTR_to_LPTSTR (LPTSTR *ppsz, BSTR bstr)
//
// Purpose: Make a LPTSTR string from an BSTR string
//
// Parameters:
// ppsz The buffer to receive a newly allocated LPTSTR string.
// bstr The BSTR string.
//
// Return Value:
// S_OK success if the string can be cloned.
// ILS_E_FAIL cannot convert the string to BSTR
// ILS_E_MEMORY cannot allocate enough memory for the BSTR string.
//****************************************************************************
HRESULT BSTR_to_LPTSTR (LPTSTR *ppsz, BSTR bstr) { #ifndef _UNICODE
LPTSTR psz; int i; HRESULT hr;
// compute the length of the required BSTR
//
i = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)bstr, -1, NULL, 0, NULL, NULL); if (i <= 0) { return ILS_E_FAIL; };
// allocate the widestr, +1 for terminating null
//
psz = (TCHAR *) ::MemAlloc (i * sizeof (TCHAR)); if (psz != NULL) { WideCharToMultiByte(CP_ACP, 0, (LPWSTR)bstr, -1, psz, i, NULL, NULL); *ppsz = psz; hr = S_OK; } else { hr = ILS_E_MEMORY; }; return hr;
#else
LPTSTR psz = NULL; HRESULT hr;
hr = SetLPTSTR(&psz, (LPTSTR)bstr);
if (hr == S_OK) { *ppsz = psz; }; return hr;
#endif // _UNICODE
}
//****************************************************************************
// CList::CList (void)
//
// Purpose: Constructor for the CList class
//
// Parameters: None
//****************************************************************************
CList::CList (void) { pHead = NULL; pTail = NULL; return; }
//****************************************************************************
// CList::~CList (void)
//
// Purpose: Constructor for the CList class
//
// Parameters: None
//****************************************************************************
CList::~CList (void) { Flush(); return; }
//****************************************************************************
// HRESULT
// CList::Insert (LPVOID pv)
//
// Purpose: Insert an object at the beginning of the list
//
// Parameters: None
//****************************************************************************
HRESULT CList::Insert (LPVOID pv) { PNODE pNode;
pNode = new NODE; if (pNode == NULL) { return ILS_E_MEMORY; };
pNode->pNext = pHead; pNode->pv = pv; pHead = pNode;
if (pTail == NULL) { // This is the first node
//
pTail = pNode; }; return NOERROR; }
//****************************************************************************
// HRESULT
// CList::Append (LPVOID pv)
//
// Purpose: Append an object to the end of the list
//
// Parameters: None
//****************************************************************************
HRESULT CList::Append (LPVOID pv) { PNODE pNode;
pNode = new NODE; if (pNode == NULL) { return ILS_E_MEMORY; };
pNode->pNext = NULL; pNode->pv = pv; if (pHead == NULL) { pHead = pNode; };
if (pTail != NULL) { pTail->pNext = pNode; }; pTail = pNode;
return NOERROR; }
//****************************************************************************
// HRESULT
// CList::Remove (LPVOID pv)
//
// Purpose: Append an object to the end of the list
//
// Parameters: None
//****************************************************************************
HRESULT CList::Remove (LPVOID pv) { PNODE pNode, pPrev; HRESULT hr;
pNode = pHead; pPrev = NULL; while (pNode != NULL) { // Matching the requested node
//
if (pNode->pv == pv) { break; // found!!!
};
pPrev = pNode; pNode = pNode->pNext; };
if (pNode != NULL) { // We found the node to remove
// Update relevant pointer
//
if (pTail == pNode) { pTail = pPrev; };
if (pPrev != NULL) { pPrev->pNext = pNode->pNext; } else { pHead = pNode->pNext; }; delete pNode; hr = NOERROR; } else { hr = S_FALSE; }; return hr; }
//****************************************************************************
// HRESULT
// CList::Find (LPVOID pv)
//
// Purpose: Find an object in the list
//
// Parameters: None
//****************************************************************************
HRESULT CList::Find (LPVOID pv) { PNODE pNode;
pNode = pHead; while (pNode != NULL) { // Matching the requested node
//
if (pNode->pv == pv) { break; // found!!!
}; pNode = pNode->pNext; };
return (pNode != NULL ? NOERROR : S_FALSE); }
//****************************************************************************
// HRESULT
// CList::FindStorage (LPVOID *ppv, LPVOID pv)
//
// Purpose: Find an object in the list and returns the object storage.
// This call is useful for search-and-replace operations.
//
// Parameters: None
//****************************************************************************
HRESULT CList::FindStorage (LPVOID *ppv, LPVOID pv) { PNODE pNode; HRESULT hr;
pNode = pHead; while (pNode != NULL) { // Matching the requested node
//
if (pNode->pv == pv) { break; // found!!!
}; pNode = pNode->pNext; };
if (pNode != NULL) { *ppv = &(pNode->pv); hr = NOERROR; } else { *ppv = NULL; hr = S_FALSE; }; return hr; }
//****************************************************************************
// HRESULT
// CList::Enumerate (HANDLE *phEnum)
//
// Purpose: Start object enumeration
//
// Parameters: None
//****************************************************************************
HRESULT CList::Enumerate (HANDLE *phEnum) { *phEnum = (HANDLE)pHead; return NOERROR; }
//****************************************************************************
// HRESULT
// CList::Next (HANDLE *phEnum, LPVOID *ppv)
//
// Purpose: Obtain the next enumerated object
//
// Parameters: None
//****************************************************************************
HRESULT CList::Next (HANDLE *phEnum, LPVOID *ppv) { PNODE pNext; HRESULT hr;
pNext = (PNODE)*phEnum;
if (pNext == NULL) { *ppv = NULL; hr = S_FALSE; } else { *ppv = pNext->pv; *phEnum = (HANDLE)(pNext->pNext); hr = NOERROR; }; return hr; }
//****************************************************************************
// HRESULT
// CList::NextStorage (HANDLE *phEnum, LPVOID *ppv)
//
// Purpose: Obtain the storage of the next enumerated object. This call is
// useful for search-and-replace operations.
//
// Parameters: None
//****************************************************************************
HRESULT CList::NextStorage (HANDLE *phEnum, LPVOID *ppv) { PNODE pNext; HRESULT hr;
pNext = (PNODE)*phEnum;
if (pNext == NULL) { *ppv = NULL; hr = S_FALSE; } else { *ppv = &(pNext->pv); *phEnum = (HANDLE)(pNext->pNext); hr = NOERROR; }; return hr; }
//****************************************************************************
// HRESULT
// CList::Flush (void)
//
// Purpose: Flush all the nodes in the list
//
// Parameters: None
//****************************************************************************
HRESULT CList::Flush (void) { PNODE pNode;
while (pHead != NULL) { pNode = pHead; pHead = pHead->pNext; delete pNode; }; return NOERROR; }
//****************************************************************************
// HRESULT
// CList::Clone (CList *pList, HANDLE *phEnum)
//
// Purpose: Flush all the nodes in the list
//
// Parameters: None
//****************************************************************************
HRESULT CList::Clone (CList *pList, HANDLE *phEnum) { PNODE pNode; HRESULT hr;
// Only allow a null list to be cloned
//
if (pHead != NULL) { return ILS_E_FAIL; };
// Traverse the source list
//
hr = S_OK; // lonchanc: in case of null list
pNode = pList->pHead; while(pNode != NULL) { // Use append to maintain the order
//
hr = Append(pNode->pv); if (FAILED(hr)) { break; };
// Get the enumerator info
//
if ((phEnum != NULL) && (*phEnum == (HANDLE)pNode)) { *phEnum = (HANDLE)pTail; }; pNode = pNode->pNext; }; return hr; }
//****************************************************************************
// CEnumNames::CEnumNames (void)
//
// History:
// Wed 17-Apr-1996 11:15:18 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
CEnumNames::CEnumNames (void) { cRef = 0; pNext = NULL; pszNames = NULL; cbSize = 0; return; }
//****************************************************************************
// CEnumNames::~CEnumNames (void)
//
// History:
// Wed 17-Apr-1996 11:15:18 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
CEnumNames::~CEnumNames (void) { if (pszNames != NULL) { ::MemFree (pszNames); }; return; }
//****************************************************************************
// STDMETHODIMP
// CEnumNames::Init (LPTSTR pList, ULONG cNames)
//
// History:
// Wed 17-Apr-1996 11:15:25 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP CEnumNames::Init (LPTSTR pList, ULONG cNames) { HRESULT hr = NOERROR;
// If no list, do nothing
//
if (cNames != 0) { LPTSTR pNextSrc; ULONG i, cLen, cbSize;
ASSERT(pList != NULL);
// Calculate the list size
//
pNextSrc = pList;
for (i = 0, cbSize = 0; i < cNames; i++) { cLen = lstrlen(pNextSrc)+1; pNextSrc += cLen; cbSize += cLen; };
// Allocate the snapshot buffer with the specified length
// plus one for doubly null-termination
//
pszNames = (TCHAR *) ::MemAlloc ((cbSize+1) * sizeof (TCHAR)); if (pszNames != NULL) { // Snapshot the name list
//
CopyMemory(pszNames, pList, cbSize*sizeof(TCHAR)); pszNames[cbSize] = '\0'; pNext = pszNames; this->cbSize = cbSize+1; } else { hr = ILS_E_MEMORY; }; }; return hr; }
//****************************************************************************
// STDMETHODIMP
// CEnumNames::QueryInterface (REFIID riid, void **ppv)
//
// History:
// Wed 17-Apr-1996 11:15:31 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP CEnumNames::QueryInterface (REFIID riid, void **ppv) { if (riid == IID_IEnumIlsNames || riid == IID_IUnknown) { *ppv = (IEnumIlsNames *) this; AddRef(); return S_OK; } else { *ppv = NULL; return ILS_E_NO_INTERFACE; }; }
//****************************************************************************
// STDMETHODIMP_(ULONG)
// CEnumNames::AddRef (void)
//
// History:
// Wed 17-Apr-1996 11:15:37 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP_(ULONG) CEnumNames::AddRef (void) { DllLock();
MyDebugMsg ((DM_REFCOUNT, "CEnumNames::AddRef: ref=%ld\r\n", cRef)); ::InterlockedIncrement ((LONG *) &cRef); return cRef; }
//****************************************************************************
// STDMETHODIMP_(ULONG)
// CEnumNames::Release (void)
//
// History:
// Wed 17-Apr-1996 11:15:43 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP_(ULONG) CEnumNames::Release (void) { DllRelease();
ASSERT (cRef > 0);
MyDebugMsg ((DM_REFCOUNT, "CEnumNames::Release: ref=%ld\r\n", cRef)); if (::InterlockedDecrement ((LONG *) &cRef) == 0) { delete this; return 0; } return cRef; }
//****************************************************************************
// STDMETHODIMP
// CEnumNames::Next (ULONG cNames, BSTR *rgpbstrName, ULONG *pcFetched)
//
// History:
// Wed 17-Apr-1996 11:15:49 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP CEnumNames::Next (ULONG cNames, BSTR *rgpbstrName, ULONG *pcFetched) { ULONG cCopied; HRESULT hr;
// Validate the pointer
//
if (rgpbstrName == NULL) return ILS_E_POINTER;
// Validate the parameters
//
if ((cNames == 0) || ((cNames > 1) && (pcFetched == NULL))) return ILS_E_PARAMETER;
// Check the enumeration index
//
cCopied = 0;
if (pNext != NULL) { // Can copy if we still have more names
//
while ((cCopied < cNames) && (*pNext != '\0')) { if (SUCCEEDED(LPTSTR_to_BSTR(&rgpbstrName[cCopied], pNext))) { cCopied++; }; pNext += lstrlen(pNext)+1; }; };
// Determine the returned information based on other parameters
//
if (pcFetched != NULL) { *pcFetched = cCopied; }; return (cNames == cCopied ? S_OK : S_FALSE); }
//****************************************************************************
// STDMETHODIMP
// CEnumNames::Skip (ULONG cNames)
//
// History:
// Wed 17-Apr-1996 11:15:56 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP CEnumNames::Skip (ULONG cNames) { ULONG cSkipped;
// Validate the parameters
//
if (cNames == 0) return ILS_E_PARAMETER;
// Check the enumeration index limit
//
cSkipped = 0;
if (pNext != NULL) { // Can skip only if we still have more attributes
//
while ((cSkipped < cNames) && (*pNext != '\0')) { pNext += lstrlen(pNext)+1; cSkipped++; }; };
return (cNames == cSkipped ? S_OK : S_FALSE); }
//****************************************************************************
// STDMETHODIMP
// CEnumNames::Reset (void)
//
// History:
// Wed 17-Apr-1996 11:16:02 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP CEnumNames::Reset (void) { pNext = pszNames; return S_OK; }
//****************************************************************************
// STDMETHODIMP
// CEnumNames::Clone(IEnumIlsNames **ppEnum)
//
// History:
// Wed 17-Apr-1996 11:16:11 -by- Viroon Touranachun [viroont]
// Created.
//****************************************************************************
STDMETHODIMP CEnumNames::Clone(IEnumIlsNames **ppEnum) { CEnumNames *peun; HRESULT hr;
// Validate parameters
//
if (ppEnum == NULL) { return ILS_E_POINTER; };
*ppEnum = NULL;
// Create an enumerator
//
peun = new CEnumNames; if (peun == NULL) return ILS_E_MEMORY;
// Clone the information
//
hr = NOERROR; peun->cbSize = cbSize; if (cbSize != 0) { peun->pszNames = (TCHAR *) ::MemAlloc (cbSize * sizeof (TCHAR)); if (peun->pszNames != NULL) { CopyMemory(peun->pszNames, pszNames, cbSize*sizeof(TCHAR)); peun->pNext = peun->pszNames+(pNext-pszNames); } else { hr = ILS_E_MEMORY; }; } else { peun->pNext = NULL; peun->pszNames = NULL; };
if (SUCCEEDED(hr)) { // Return the cloned enumerator
//
peun->AddRef(); *ppEnum = peun; } else { delete peun; }; return hr; }
/* F L E G A L E M A I L S Z */ /*-------------------------------------------------------------------------
%%Function: FLegalEmailSz
RobD created A legal email name contains only ANSI characters. "a-z, A-Z, numbers 0-9 and some common symbols" It cannot include extended characters or < > ( ) /
loncahnc modified IsLegalEmailName ( TCHAR *pszName ). A legal email name contains RFC 822 compliant characters. -------------------------------------------------------------------------*/
BOOL IsLegalEmailName ( TCHAR *pszName ) { // Null string is not legal
//
if (pszName == NULL) return FALSE;
TCHAR ch; while ((ch = *pszName++) != TEXT ('\0')) { switch (ch) { default: // Check if ch is in the range
//
if (ch > TEXT (' ') && ch <= TEXT ('~')) break;
// Fall thru to error code
//
case TEXT ('('): case TEXT (')'): case TEXT ('<'): case TEXT ('>'): case TEXT ('['): case TEXT (']'): case TEXT ('/'): case TEXT ('\\'): case TEXT (','): case TEXT (';'): case TEXT (':'): case TEXT ('\"'): return FALSE; } } // while
return TRUE; }
|