#include "std.hxx" void xGetOverlappedResult( HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumberOfBytesTransferred, BOOL bWait) { BOOL bResult = ::GetOverlappedResult( hFile, lpOverlapped, lpNumberOfBytesTransferred, bWait); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("GetOverlappedResult")); } } HANDLE xCreateFile( PCTSTR pcszFileName, // file name DWORD dwDesiredAccess, // access mode DWORD dwShareMode, // share mode PSECURITY_ATTRIBUTES pSecurityAttributes, // SD DWORD dwCreationDisposition, // how to create DWORD dwFlagsAndAttributes, // file attributes HANDLE hTemplateFile) // handle to template file { HANDLE hTemp = ::CreateFile( pcszFileName, dwDesiredAccess, dwShareMode, pSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); if (INVALID_HANDLE_VALUE==hTemp) { throw CWin32ApiExcept( GetLastError(), _T("CreateFile")); } return hTemp; } void xCloseHandle( HANDLE hObject) // handle to object { BOOL bResult = ::CloseHandle( hObject); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("CloseHandle")); } } BOOL xReadFile( HANDLE hFile, // handle to file PVOID pBuffer, // data buffer DWORD dwNumberOfBytesToRead, // number of bytes to read PDWORD pdwNumberOfBytesRead, // number of bytes read LPOVERLAPPED pOverlapped) // overlapped buffer { BOOL bResult = ::ReadFile( hFile, pBuffer, dwNumberOfBytesToRead, pdwNumberOfBytesRead, pOverlapped); if (!bResult && (GetLastError()!=ERROR_IO_PENDING)) { throw CWin32ApiExcept( GetLastError(), _T("ReadFile")); } return bResult; } void xReadFileWithAbort( HANDLE hFile, // handle to file PVOID pBuffer, // data buffer DWORD dwNumberOfBytesToRead, // number of bytes to read PDWORD pdwNumberOfBytesRead, // number of bytes read LPOVERLAPPED pOverlapped, // overlapped buffer HANDLE hAbort) // Handle to manual reset abort event { HANDLE hWait[2]; hWait[0] = hAbort; hWait[1] = pOverlapped->hEvent; BOOL bResult = xReadFile( hFile, // handle to file pBuffer, // data buffer dwNumberOfBytesToRead, // number of bytes to read pdwNumberOfBytesRead, // number of bytes read pOverlapped); // overlapped buffer if (!bResult) { DWORD dwResult = xWaitForMultipleObjects( 2, // There are two to wait on hWait, // Our two event handles FALSE, // Only one event need to be pinged INFINITE); // Wait for ever switch (dwResult) { case (WAIT_OBJECT_0): CancelIo( hFile); throw CAbortExcept(); break; case (WAIT_OBJECT_0 + 1): xGetOverlappedResult( hFile, pOverlapped, pdwNumberOfBytesRead, TRUE); break; } } } BOOL xWriteFile( HANDLE hFile, // handle to file LPCVOID pBuffer, // data buffer DWORD dwNumberOfBytesToWrite, // number of bytes to write PDWORD pdwNumberOfBytesWritten, // number of bytes written LPOVERLAPPED pOverlapped) // overlapped buffer { BOOL bResult = ::WriteFile( hFile, pBuffer, dwNumberOfBytesToWrite, pdwNumberOfBytesWritten, pOverlapped); if (!bResult && (GetLastError()!=ERROR_IO_PENDING)) { throw CWin32ApiExcept( GetLastError(), _T("WriteFile")); } return bResult; } void xWriteFileWithAbort( HANDLE hFile, // handle to file LPCVOID pBuffer, // data buffer DWORD dwNumberOfBytesToWrite, // number of bytes to write PDWORD pdwNumberOfBytesWritten, // number of bytes written LPOVERLAPPED pOverlapped, // overlapped buffer HANDLE hAbort) // Handle to manual reset abort event { HANDLE hWait[2]; hWait[0] = hAbort; hWait[1] = pOverlapped->hEvent; BOOL bResult = xWriteFile( hFile, // handle to file pBuffer, // data buffer dwNumberOfBytesToWrite, // number of bytes to read pdwNumberOfBytesWritten, // number of bytes read pOverlapped); // overlapped buffer if (!bResult) { DWORD dwResult = xWaitForMultipleObjects( 2, // There are two to wait on hWait, // Our two event handles FALSE, // Only one event need to be pinged INFINITE); // Wait for ever switch (dwResult) { case (WAIT_OBJECT_0): CancelIo( hFile); throw CAbortExcept(); break; case (WAIT_OBJECT_0 + 1): xGetOverlappedResult( hFile, pOverlapped, pdwNumberOfBytesWritten, TRUE); break; } } } void xGetCommState( HANDLE hFile, // handle to communications device LPDCB pDCB) // device-control block { BOOL bResult = ::GetCommState( hFile, pDCB); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("GetCommState")); } } void xSetCommState( HANDLE hFile, // handle to communications device LPDCB pDCB) // device-control block { BOOL bResult = ::SetCommState( hFile, pDCB); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("SetCommState")); } } void xGetCommTimeouts( HANDLE hFile, // handle to comm device LPCOMMTIMEOUTS pCommTimeouts) // time-out values { BOOL bResult = ::GetCommTimeouts( hFile, pCommTimeouts); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("GetCommTimeouts")); } } void xSetCommTimeouts( HANDLE hFile, // handle to comm device LPCOMMTIMEOUTS pCommTimeouts) // time-out values { BOOL bResult = ::SetCommTimeouts( hFile, pCommTimeouts); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("SetCommTimeouts")); } } void xSetCommMask( HANDLE hFile, // handle to communications device DWORD dwEvtMask) // mask that identifies enabled events { BOOL bResult = ::SetCommMask( hFile, dwEvtMask); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("SetCommMask")); } } void xGetCommMask( HANDLE hFile, // handle to communications device PDWORD pdwEvtMask) // mask that identifies enabled events { BOOL bResult = ::GetCommMask( hFile, pdwEvtMask); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("GetCommMask")); } } BOOL xWaitCommEvent( HANDLE hFile, // handle to comm device PDWORD pdwEvtMask, // event type LPOVERLAPPED pOverlapped) // overlapped structure { BOOL bResult = ::WaitCommEvent( hFile, pdwEvtMask, pOverlapped); if (!bResult && (GetLastError()!=ERROR_IO_PENDING)) { throw CWin32ApiExcept( GetLastError(), _T("WaitCommEvent")); } return bResult; } void xWaitCommEventWithAbort( HANDLE hFile, // handle to comm device PDWORD pdwEvtMask, // event type LPOVERLAPPED pOverlapped, // overlapped structure HANDLE hAbort) // Manual reset abort event { HANDLE hWait[2]; hWait[0] = hAbort; hWait[1] = pOverlapped->hEvent; DWORD dwBytesRead; BOOL bResult = xWaitCommEvent( hFile, pdwEvtMask, pOverlapped); if (!bResult) { DWORD dwResult = xWaitForMultipleObjects( 2, // There are two to wait on hWait, // Our two event handles FALSE, // Only one event need to be pinged INFINITE); // Wait for ever switch (dwResult) { case (WAIT_OBJECT_0): CancelIo( hFile); throw CAbortExcept(); break; case (WAIT_OBJECT_0 + 1): xGetOverlappedResult( hFile, pOverlapped, &dwBytesRead, TRUE); break; } } } void xEscapeCommFunction( HANDLE hFile, // handle to communications device DWORD dwFunc) // extended function to perform { BOOL bResult = ::EscapeCommFunction( hFile, dwFunc); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("EscapeCommFunction")); } } void xClearCommBreak( HANDLE hFile) // handle to communications device { BOOL bResult = ::ClearCommBreak( hFile); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("ClearCommBreak")); } } void xClearCommError( HANDLE hFile, // handle to communications device PDWORD pdwErrors, // error codes LPCOMSTAT pStat) // communications status { BOOL bResult = ::ClearCommError( hFile, pdwErrors, pStat); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("ClearCommError")); } } void xBuildCommDCB( PCTSTR pcszDef, // device-control string LPDCB lpDCB) // device-control block { BOOL bResult = ::BuildCommDCB( pcszDef, lpDCB); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("BuildCommDCB")); } } void xTransmitCommChar( HANDLE hFile, char cChar) { BOOL bResult = ::TransmitCommChar( hFile, cChar); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("TransmitCommChar")); } } HANDLE xCreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD DWORD dwStackSize, // initial stack size LPTHREAD_START_ROUTINE lpStartAddress, // thread function LPVOID lpParameter, // thread argument DWORD dwCreationFlags, // creation option LPDWORD lpThreadId) // thread identifier { HANDLE hResult = ::CreateThread( lpThreadAttributes, // SD dwStackSize, // initial stack size lpStartAddress, // thread function lpParameter, // thread argument dwCreationFlags, // creation option lpThreadId); // thread identifier if (NULL==hResult) { throw CWin32ApiExcept( GetLastError(), _T("CreateThread")); } return hResult; } void xTerminateThread( HANDLE hThread, // handle to thread DWORD dwExitCode) // exit code { throw CWin32ApiExcept( GetLastError(), _T("TerminateThread")); } UINT_PTR xSetTimer( HWND hWnd, // handle to window UINT_PTR nIDEvent, // timer identifier UINT uElapse, // time-out value TIMERPROC lpTimerFunc) // timer procedure { UINT_PTR pResult = ::SetTimer( hWnd, nIDEvent, uElapse, lpTimerFunc); if (0 == pResult) { throw CWin32ApiExcept( GetLastError(), _T("SetTimer")); } return pResult; } void xKillTimer( HWND hWnd, // handle to window UINT_PTR uIDEvent) // timer identifier { BOOL bResult = ::KillTimer( hWnd, uIDEvent); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("KillTimer")); } } void xFillConsoleOutputAttribute( HANDLE hConsoleOutput, WORD wAttribute, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfAttrsWritten) { BOOL bResult = ::FillConsoleOutputAttribute( hConsoleOutput, wAttribute, nLength, dwWriteCoord, lpNumberOfAttrsWritten); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("FillConsoleOutputAttribute")); } } void xFillConsoleOutputCharacter( HANDLE hConsoleOutput, TCHAR cCharacter, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten) { BOOL bResult = ::FillConsoleOutputCharacter( hConsoleOutput, cCharacter, nLength, dwWriteCoord, lpNumberOfCharsWritten); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("FillConsoleOutputCharacter")); } } void xGetConsoleScreenBufferInfo( HANDLE hConsoleOutput, PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo) { BOOL bResult = ::GetConsoleScreenBufferInfo( hConsoleOutput, lpConsoleScreenBufferInfo); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("GetConsoleScreenBufferInfo")); } } DWORD xGetConsoleTitle( LPTSTR lpConsoleTitle, DWORD nSize) { DWORD dwResult = ::GetConsoleTitle( lpConsoleTitle, nSize); if (!dwResult) { throw CWin32ApiExcept( GetLastError(), _T("GetConsoleTitle")); } return dwResult; } COORD xGetLargestConsoleWindowSize( HANDLE hConsoleOutput) { COORD Result = ::GetLargestConsoleWindowSize( hConsoleOutput); if (0==Result.X && 0==Result.Y) { throw CWin32ApiExcept( GetLastError(), _T("GetLargestConsoleWindowSize")); } return Result; } HANDLE xGetStdHandle( DWORD nStdHandle) { HANDLE hResult = ::GetStdHandle( nStdHandle); if (INVALID_HANDLE_VALUE==hResult) { throw CWin32ApiExcept( GetLastError(), _T("GetStdHandle")); } return hResult; } void xReadConsoleOutputAttribute( HANDLE hConsoleOutput, LPWORD lpAttribute, DWORD nLength, COORD dwReadCoord, LPDWORD lpNumberOfAttrsRead) { BOOL bResult = ::ReadConsoleOutputAttribute( hConsoleOutput, lpAttribute, nLength, dwReadCoord, lpNumberOfAttrsRead); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("ReadConsoleOutputAttribute")); } } void xReadConsoleOutputCharacter( HANDLE hConsoleOutput, LPTSTR lpCharacter, DWORD nLength, COORD dwReadCoord, LPDWORD lpNumberOfCharsRead) { BOOL bResult = ::ReadConsoleOutputCharacter( hConsoleOutput, lpCharacter, nLength, dwReadCoord, lpNumberOfCharsRead); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("ReadConsoleOutputCharacter")); } } void xSetConsoleScreenBufferSize( HANDLE hConsoleOutput, COORD dwSize) { BOOL bResult = ::SetConsoleScreenBufferSize( hConsoleOutput, dwSize); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("SetConsoleScreenBufferSize")); } } void xSetConsoleTextAttribute( HANDLE hConsoleOutput, WORD wAttributes) { BOOL bResult = ::SetConsoleTextAttribute( hConsoleOutput, wAttributes); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("SetConsoleTextAttribute")); } } void xSetConsoleTitle( LPCTSTR lpConsoleTitle) { BOOL bResult = ::SetConsoleTitle( lpConsoleTitle); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("SetConsoleTitle")); } } void xSetConsoleWindowInfo( HANDLE hConsoleOutput, BOOL bAbsolute, CONST SMALL_RECT *lpConsoleWindow) { BOOL bResult = ::SetConsoleWindowInfo( hConsoleOutput, bAbsolute, lpConsoleWindow); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("SetConsoleWindowInfo")); } } void xWriteConsole( HANDLE hConsoleOutput, CONST VOID *lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved) { BOOL bResult = ::WriteConsole( hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("WriteConsole")); } } void xWriteConsoleOutputAttribute( HANDLE hConsoleOutput, CONST WORD *lpAttribute, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfAttrsWritten) { BOOL bResult = ::WriteConsoleOutputAttribute( hConsoleOutput, lpAttribute, nLength, dwWriteCoord, lpNumberOfAttrsWritten); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("WriteConsoleOutputAttribute")); } } void xWriteConsoleOutputCharacter( HANDLE hConsoleOutput, LPCTSTR lpCharacter, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten) { BOOL bResult = ::WriteConsoleOutputCharacter( hConsoleOutput, lpCharacter, nLength, dwWriteCoord, lpNumberOfCharsWritten); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("WriteConsoleOutputCharacter")); } } HANDLE xCreateEvent( LPSECURITY_ATTRIBUTES lpEventAttributes, // SD BOOL bManualReset, // reset type BOOL bInitialState, // initial state LPCTSTR lpName) // object name { HANDLE hResult = ::CreateEvent( lpEventAttributes, bManualReset, bInitialState, lpName); if (INVALID_HANDLE_VALUE==hResult) { throw CWin32ApiExcept( GetLastError(), _T("CreateEvent")); } return hResult; } void xSetEvent( HANDLE hEvent) { BOOL bResult = ::SetEvent( hEvent); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("SetEvent")); } } void xResetEvent( HANDLE hEvent) { BOOL bResult = ::ResetEvent( hEvent); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("ResetEvent")); } } DWORD xWaitForMultipleObjects( DWORD nCount, // number of handles in array CONST HANDLE *lpHandles, // object-handle array BOOL fWaitAll, // wait option DWORD dwMilliseconds) // time-out interval { DWORD dwResult = ::WaitForMultipleObjects( nCount, lpHandles, fWaitAll, dwMilliseconds); if (WAIT_FAILED==dwResult) { throw CWin32ApiExcept( GetLastError(), _T("WaitForMultipleObjects")); } return dwResult; } DWORD xWaitForSingleObject( HANDLE hHandle, // handle to object DWORD dwMilliseconds) // time-out interval { DWORD dwResult = ::WaitForSingleObject( hHandle, // handle to object dwMilliseconds); // time-out interval if (WAIT_FAILED==dwResult) { throw CWin32ApiExcept( GetLastError(), _T("WaitForSingleObject")); } return dwResult; } PWSTR xMultiByteToWideChar( UINT CodePage, // code page DWORD dwFlags, // performance and mapping flags LPCSTR lpMultiByteStr) // wide-character string { int dResult = ::MultiByteToWideChar( CodePage, dwFlags, lpMultiByteStr, -1, NULL, 0); if (dResult==0) { throw CWin32ApiExcept( GetLastError(), _T("MultiByteToWideChar")); } auto_ptr pszOutput( new WCHAR[dResult]); dResult = ::MultiByteToWideChar( CodePage, dwFlags, lpMultiByteStr, -1, pszOutput.get(), dResult); if (dResult==0) { throw CWin32ApiExcept( GetLastError(), _T("MultiByteToWideChar")); } return pszOutput.release(); } PSTR xWideCharToMultiByte( UINT CodePage, // code page DWORD dwFlags, // performance and mapping flags LPCWSTR lpWideCharStr) // wide-character string { int dResult = ::WideCharToMultiByte( CodePage, dwFlags, lpWideCharStr, -1, NULL, 0, NULL, NULL); if (dResult==0) { throw CWin32ApiExcept( GetLastError(), _T("WideCharToMultiByte")); } auto_ptr pszOutput( new CHAR[dResult]); dResult = ::WideCharToMultiByte( CodePage, dwFlags, lpWideCharStr, -1, pszOutput.get(), dResult, NULL, NULL); if (dResult==0) { throw CWin32ApiExcept( GetLastError(), _T("WideCharToMultiByte")); } return pszOutput.release(); } PWSTR xMakeWideChar( PTSTR pcszInput) { #ifdef _UNICODE auto_ptr pszOutput( new WCHAR[wcslen(pcszInput)+1]); wcscpy( pszOutput.get(), pcszInput); #else auto_ptr pszOutput( xMultiByteToWideChar( CP_ACP, 0, pcszInput)); #endif return pszOutput.release(); } PSTR xMakeMultiByte( PTSTR pcszInput) { #ifdef _UNICODE auto_ptr pszOutput( xWideCharToMultiByte( CP_ACP, 0, pcszInput)); #else auto_ptr pszOuptut( new CHAR[strlen(pcszInput)+1]); strcpy( pszOutput.get(), pcszInput); #endif return pszOutput.release(); } PTSTR xMakeDefaultChar( PWSTR pcszInput) { #ifdef _UNICODE auto_ptr pszOutput( new WCHAR[wcslen(pcszInput)+1]); wcscpy( pszOutput.get(), pcszInput); #else auto_ptr pszOuptut( xWideCharToMultiByte( CP_ACP, 0, pcszInput)); #endif return pszOutput.release(); } PTSTR xMakeDefaultChar( PSTR pcszInput) { #ifdef _UNICODE auto_ptr pszOutput( xMultiByteToWideChar( CP_ACP, 0, pcszInput)); #else auto_ptr pszOuptut( new CHAR[strlen(pcszInput)+1]); strcpy( pszOutput.get(), pcszInput); #endif return pszOutput.release(); } DWORD xGetModuleFileName( HMODULE hModule, // handle to module LPTSTR lpFilename, // file name of module DWORD nSize) // size of buffer { DWORD dwResult = ::GetModuleFileName( hModule, lpFilename, nSize); if (0==dwResult) { throw CWin32ApiExcept( GetLastError(), _T("GetModuleFileName")); } if (dwResult == nSize) // This will happen if { SetLastError(ERROR_INSUFFICIENT_BUFFER); return 0; } else { return dwResult; } } HANDLE xFindFirstFile( LPCTSTR lpFileName, // file name LPWIN32_FIND_DATA lpFindFileData) // data buffer { HANDLE hResult = ::FindFirstFile( lpFileName, lpFindFileData); if (INVALID_HANDLE_VALUE==hResult && GetLastError()!=ERROR_NO_MORE_FILES) { throw CWin32ApiExcept( GetLastError(), _T("FindFirstFile")); } return hResult; } BOOL xFindNextFile( HANDLE hFindFile, // search handle LPWIN32_FIND_DATA lpFindFileData) // data buffer { BOOL fResult = ::FindNextFile( hFindFile, lpFindFileData); if (!fResult && GetLastError()!=ERROR_NO_MORE_FILES) { throw CWin32ApiExcept( GetLastError(), _T("FindNextFile")); } return fResult; } HMODULE xLoadLibrary( LPCTSTR lpFileName) // file name of module { HMODULE hResult = ::LoadLibrary( lpFileName); if (NULL==hResult) { throw CWin32ApiExcept( GetLastError(), _T("LoadLibrary")); } return hResult; } BOOL xFreeLibrary( HMODULE hModule) // handle to DLL module { BOOL bResult = ::FreeLibrary( hModule); if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("FreeLibrary")); } return bResult; } FARPROC xGetProcAddress( HMODULE hModule, LPCSTR lpProcName) { FARPROC pResult = ::GetProcAddress( hModule, lpProcName); if (NULL==pResult) { throw CWin32ApiExcept( GetLastError(), _T("GetProcAddress")); } return pResult; } CFindFile::~CFindFile() { if (m_hFind!=INVALID_HANDLE_VALUE) { FindClose(m_hFind); } } BOOL CFindFile::First(PCTSTR pcszFileName) { if (m_hFind!=INVALID_HANDLE_VALUE) { FindClose(m_hFind); } m_hFind = xFindFirstFile( pcszFileName, &m_FindData); return (m_hFind!=INVALID_HANDLE_VALUE); } BOOL CFindFile::Next() { return xFindNextFile( m_hFind, &m_FindData); } PWIN32_FIND_DATA CFindFile::Found() { return &m_FindData; } HANDLE xCreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes, // SD BOOL bInitialOwner, // initial owner LPCTSTR lpName) // object name { HANDLE hResult = ::CreateMutex( lpMutexAttributes, // SD bInitialOwner, // initial owner lpName); // object name if (NULL==hResult) { throw CWin32ApiExcept( GetLastError(), _T("CreateMutex")); } return hResult; } void xReleaseMutex( HANDLE hMutex) { BOOL bResult = ::ReleaseMutex( hMutex); // mutex object handle if (!bResult) { throw CWin32ApiExcept( GetLastError(), _T("ReleaseMutex")); } } PTSTR xFormatMessage( DWORD dwFlags, // source and processing options LPCVOID lpSource, // message source DWORD dwMessageId, // message identifier DWORD dwLanguageId, // language identifier LPTSTR lpBuffer, // message buffer DWORD nSize, // maximum size of message buffer va_list *Arguments) // array of message inserts { auto_ptr pszMessage; PTSTR pszTempBuffer; DWORD dwResult = ::FormatMessage( dwFlags, lpSource, dwMessageId, dwLanguageId, (LPTSTR)&pszTempBuffer, nSize, Arguments); if (dwResult==0) { throw CWin32ApiExcept( GetLastError(), _T("FormatMessage")); } try { auto_ptr pszMessage( new TCHAR[_tcslen(pszTempBuffer)+1]); _tcscpy( pszMessage.get(), pszTempBuffer); if (lpBuffer!=NULL) { *((PTSTR*)lpBuffer) = pszMessage.get(); } LocalFree( pszTempBuffer); return pszMessage.release(); } catch (...) { // // This needs to be freed regardless. // LocalFree( pszTempBuffer); throw; } }