windows-nt/Source/XPSP1/NT/shell/shdocvw/smallutil.hpp
2020-09-26 16:20:57 +08:00

260 lines
5.9 KiB
C++

#ifndef _SMALLUTIL_H_
#define _SMALLUTIL_H_
// CCancellableThread
//
// Lets you define a thread object that can be cancelled by the creator.
//To implement the thread, derivce from CCancellableThread and override the
//run() function. run() will be ran in its own thread, and the value returned
//by run can be accessed by GetResult(). run() should check IsCancelled()
//at appropriate intervals and exit early if true.
// Clients of the cancellable thread then create the object, and execute Run()
//when ready. If they wish to cancel, they can call NotifyCancel().
typedef class CCancellableThread
{
private:
HANDLE _hCancelEvent;
HANDLE _hThread;
static DWORD WINAPI threadProc( LPVOID lpParameter);
BOOL _fIsFinished;
DWORD _dwThreadResult;
public:
CCancellableThread();
~CCancellableThread();
virtual BOOL Initialize();
BOOL IsCancelled();
BOOL IsRunning();
BOOL IsFinished();
BOOL GetResult( PDWORD pdwResult);
BOOL Run();
BOOL NotifyCancel();
BOOL WaitForNotRunning( DWORD dwMilliseconds, PBOOL pfFinished = NULL);
BOOL WaitForCancel( DWORD dwMilliseconds, PBOOL pfCancelled = NULL);
protected:
virtual DWORD run() = 0;
}*PCCancellableThread;
// CQueueSortOf - a queue(sort of) used to store stuff
//in a renumerable way..
class CQueueSortOf
{
// This sort-of-queue is just a data structure to build up a list of items
//(always adding to the end) and then be able to enumerate that list
//repeatedly from start to end.
// The list does not own any of the objects added to it..
typedef struct SEntry
{
SEntry* pNext;
void* data;
} *PSEntry;
PSEntry m_pHead, m_pTail;
public:
CQueueSortOf()
{
m_pHead = NULL;
m_pTail = NULL;
}
~CQueueSortOf()
{
while( m_pHead != NULL)
{
PSEntry temp = m_pHead;
m_pHead = m_pHead->pNext;
delete temp;
}
}
bool InsertAtEnd( void* newElement)
{
PSEntry pNewEntry = new SEntry;
if( pNewEntry == NULL)
return false;
pNewEntry->data = newElement;
pNewEntry->pNext = NULL;
if( m_pHead == NULL)
{
m_pHead = m_pTail = pNewEntry;
}
else
{
m_pTail->pNext = pNewEntry;
m_pTail = pNewEntry;
}
return true;
}
// enumerations are managed by an 'iterator' which simply a void pointer into
//the list. To start an enumeration, pass NULL as the iterator. The end
//of enumeration will be indicated by a NULL iterator being returned.
void* StepEnumerate( void* iterator)
{
return (iterator == NULL) ? m_pHead : ((PSEntry)iterator)->pNext;
}
void* Get( void* iterator)
{
return ((PSEntry)iterator)->data;
}
};
// CGrowingString is a simple utility class that allows you to create
//a string and append to it without worrying about reallocating memory
//every time.
class CGrowingString
{
public:
WCHAR* m_szString;
long m_iBufferSize;
long m_iStringLength;
CGrowingString()
{
m_szString = NULL;
m_iBufferSize = 0;
m_iStringLength = 0;
}
~CGrowingString()
{
delete[] m_szString;
}
BOOL AppendToString( LPCWSTR pszNew)
{
long iLength = lstrlen( pszNew);
if( m_szString == NULL
|| m_iStringLength + iLength + 1 > m_iBufferSize)
{
long iNewSize = max(1024, m_iStringLength + iLength * 10);
WCHAR* pNewBuffer = new WCHAR[iNewSize];
if( pNewBuffer == NULL)
return FALSE;
if( m_szString == NULL)
{
m_szString = pNewBuffer;
m_iBufferSize = iNewSize;
}
else
{
StrCpyNW( pNewBuffer, m_szString, m_iStringLength + 1);
delete[] m_szString;
m_szString = pNewBuffer;
m_iBufferSize = iNewSize;
}
}
StrCpyNW( m_szString + m_iStringLength, pszNew, iLength+1);
m_iStringLength += iLength;
m_szString[m_iStringLength] = L'\0';
return TRUE;
}
};
//****************************************************
//
// FileOutputStream - retrofitted for WCHAR
// from wininet\cookexp.cpp
class CFileOutputStream
{
public:
CFileOutputStream()
{
m_hFile = INVALID_HANDLE_VALUE;
m_fError = FALSE;
m_dwLastError = 0;
}
~CFileOutputStream()
{
if( m_hFile != INVALID_HANDLE_VALUE)
CloseHandle( m_hFile);
}
BOOL Load( LPCWSTR szFilename, BOOL fAppend)
{
m_hFile = CreateFile( szFilename, GENERIC_WRITE | GENERIC_READ, 0, NULL,
fAppend ? OPEN_ALWAYS : CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if( m_hFile == INVALID_HANDLE_VALUE)
{
m_fError = TRUE;
m_dwLastError = GetLastError();
return FALSE;
}
if( fAppend
&& SetFilePointer( m_hFile, 0, NULL, FILE_END) == 0xFFFFFFFF)
{
m_fError = TRUE;
m_dwLastError = GetLastError();
return FALSE;
}
return TRUE;
}
BOOL DumpStr( const CHAR* szString, DWORD cLength)
{
DWORD dwTemp;
if( m_fError == TRUE)
return FALSE;
if( WriteFile( m_hFile, szString, cLength, &dwTemp, NULL) == TRUE)
{
return TRUE;
}
else
{
m_fError = TRUE;
m_dwLastError = GetLastError();
return FALSE;
}
}
BOOL WriteNewline()
{
static const LPCSTR szNewLine = "\r\n";
return DumpStr( szNewLine, sizeof( szNewLine) - 1);
}
BOOL IsError()
{
return m_fError;
}
private:
HANDLE m_hFile;
BOOL m_fError;
DWORD m_dwLastError;
};
#endif