The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#ifndef __MISC_H
#define __MISC_H

#include <windows.h>


///////////////////////////////////////////////////////////////////////////////
//
// functions
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
// allocates memory and initializes the memory with null
//
// param:	 size - size to allocate in bytes
//
// return: ptr to the allocated memory
//
// note:	 if there is not enougth memory, a STATUS_NO_MEMORY exception will be
//				 raised
//
///////////////////////////////////////////////////////////////////////////////

PSTR NewMem(DWORD size);

///////////////////////////////////////////////////////////////////////////////
//
// reallocates memory
//
// param:	 oldPtr - pointer to the current memory
//				 size		- new size in bytes
//				 reinit - if true, rezero the memory
//
// return: ptr to the allocated memory
//
// note:	 if there is not enougth memory, a STATUS_NO_MEMORY exception will be
//				 raised
//
///////////////////////////////////////////////////////////////////////////////

PSTR NewMem(PVOID oldPtr, DWORD size, int reinit);

///////////////////////////////////////////////////////////////////////////////
//
// allocates memory for a string and copies the contents of str to the
// allocated string
//
// param:	 str - pointer to string to copy
//
// return: ptr to the allocated memory
//
// note:	 if there is not enougth memory, a STATUS_NO_MEMORY exception will be
//				 raised
//
///////////////////////////////////////////////////////////////////////////////

PSTR NewStr(PSTR str);

///////////////////////////////////////////////////////////////////////////////
//
// allocates memory for a unicode string and copies the contents of str to the
// allocated string
//
// param:	 str - pointer to string to copy
//
// return: ptr to the allocated memory
//
// note:	 if there is not enougth memory, a STATUS_NO_MEMORY exception will be
//				 raised
//
///////////////////////////////////////////////////////////////////////////////

PWSTR NewStr(PWSTR str);

///////////////////////////////////////////////////////////////////////////////
//
// allocates memory for a unicode string and copies the contents of str to the
// allocated string
//
// param:	 str - pointer to string to copy
//
// return: ptr to the allocated memory
//
// note:	 if there is not enougth memory, a STATUS_NO_MEMORY exception will be
//				 raised
//
///////////////////////////////////////////////////////////////////////////////

PWSTR NewStrAsWide(PSTR str);

///////////////////////////////////////////////////////////////////////////////
//
// frees memory
//
// param:	 ptr - pointer to the memory
//
// return: 1 - success
//				 0 - failure
//
///////////////////////////////////////////////////////////////////////////////

int FreeMem(PVOID ptr);

///////////////////////////////////////////////////////////////////////////////
//
// frees memory from an array
//
// param:	 ptr  - pointer to the array
//				 size - number of array items
//
// return: 1 - success
//				 0 - failure
//
///////////////////////////////////////////////////////////////////////////////

int FreeArray(PVOID *ptr, DWORD size);

///////////////////////////////////////////////////////////////////////////////
//
// copies exception code
//
// param:	 code		 - exception code
//				 codePtr - destination pointer
//
// return: always 1
//
// note:	 don't call this directly; use the SetExceptCode macro instead
//
///////////////////////////////////////////////////////////////////////////////

int SaveExceptionCode(DWORD code, PDWORD codePtr);

///////////////////////////////////////////////////////////////////////////////
//
// copies exception information
//
// param:	 exception - pointer to the exception information
//				 exceptPtr - destination pointer
//
// return: always 1
//
// note:	 don't call this directly; use the SetExceptInfo macro instead
//
///////////////////////////////////////////////////////////////////////////////

int SaveExceptionInformation(PEXCEPTION_POINTERS exception,
                             PEXCEPTION_POINTERS exceptPtr);


///////////////////////////////////////////////////////////////////////////////
//
// macros
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
// gets the exception code and copies it to the except variable
//
///////////////////////////////////////////////////////////////////////////////

#define SetExceptCode(except) SaveExceptionCode(GetExceptionCode(), &except)

///////////////////////////////////////////////////////////////////////////////
//
// gets the exception information and copies it to the except variable
//
///////////////////////////////////////////////////////////////////////////////

#define SetExceptInfo(except) SaveExceptionInformation(GetExceptionInformation(), &except)

///////////////////////////////////////////////////////////////////////////////
//
// defines the variables error, excode and result
//
///////////////////////////////////////////////////////////////////////////////

#define ErrorAndResult  DWORD error = 0, excode = 0; BOOL result = TRUE;

///////////////////////////////////////////////////////////////////////////////
//
// defines the variables except, context and exception
//
///////////////////////////////////////////////////////////////////////////////

#define ExceptInfo EXCEPTION_RECORD except; CONTEXT context;    \
  EXCEPTION_POINTERS exception = {&except, &context};           \
  ZeroMemory(&except, sizeof(except));                          \
  ZeroMemory(&context, sizeof(context));

///////////////////////////////////////////////////////////////////////////////
//
// gets the last error, sets result to false and generates an exception
//
///////////////////////////////////////////////////////////////////////////////

#define RaiseFalse()                                    \
  ( ( error = GetLastError() ), ( result = FALSE ),     \
    ( RaiseException(0xEFFFFFFF, 0, 0, NULL) ) )

///////////////////////////////////////////////////////////////////////////////
//
// gets the last error, sets result to true and generates an exception
//
///////////////////////////////////////////////////////////////////////////////

#define RaiseTrue()                                     \
  ( ( error = GetLastError() ), ( result = TRUE ),      \
    ( RaiseException(0xEFFFFFFF, 0, 0, NULL) ) )

///////////////////////////////////////////////////////////////////////////////
//
// sets the last error, sets result to false and generates an exception
//
///////////////////////////////////////////////////////////////////////////////

#define RaiseFalseError(errorNo) ( SetLastError(error = errorNo), RaiseFalse() )

///////////////////////////////////////////////////////////////////////////////
//
// sets the last error, sets result to true and generates an exception
//
///////////////////////////////////////////////////////////////////////////////

#define RaiseTrueError(errorNo) ( SetLastError(error = errorNo), RaiseTrue() )

///////////////////////////////////////////////////////////////////////////////
//
// gets the last error, sets result to false and leaves
//
///////////////////////////////////////////////////////////////////////////////

#define LeaveFalse()                                    \
  { error = GetLastError(); result = FALSE; __leave; }

///////////////////////////////////////////////////////////////////////////////
//
// gets the last error, sets result to true and leaves
//
///////////////////////////////////////////////////////////////////////////////

#define LeaveTrue()                                     \
  { error = GetLastError(); result = TRUE; __leave; }

///////////////////////////////////////////////////////////////////////////////
//
// sets the last error, sets result to false and leaves
//
///////////////////////////////////////////////////////////////////////////////

#define LeaveFalseError(errorNo) { SetLastError(error = errorNo); LeaveFalse(); }

///////////////////////////////////////////////////////////////////////////////
//
// sets the last error, sets result to true and leaves
//
///////////////////////////////////////////////////////////////////////////////

#define LeaveTrueError(errorNo) { SetLastError(error = errorNo); LeaveTrue(); }

///////////////////////////////////////////////////////////////////////////////
//
// sets the lastError variable
//
///////////////////////////////////////////////////////////////////////////////

#define SetErrorVar()                                           \
  ( lastError ? ( *lastError = error ? error : excode ) : 0 )

///////////////////////////////////////////////////////////////////////////////
//
// resets the lastError variable to null
//
///////////////////////////////////////////////////////////////////////////////

#define ResetErrorVar() ( lastError ? *lastError = 0 : 0 )

///////////////////////////////////////////////////////////////////////////////
//
// macros to clean up resources; there are always three macros:
// Clean*				- frees the resource and sets the resource to null
// Clean*OnErr	- calls Clean* if the error variable is set
// Clean*OnCond	-	calls Clean* if the condition is true
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
// closes an handle
//
///////////////////////////////////////////////////////////////////////////////

#define CleanHandle(handle)                                             \
  ( ( ( handle ) ? ( CloseHandle(handle), handle = NULL, 1 ) : 1 ) )

#define CleanHandleOnErr(handle)                        \
  ( ( ( error ) ? ( CleanHandle(handle) ) : 1 ) )

#define CleanHandleOnCond(handle, cond)                 \
  ( ( ( cond ) ? ( CleanHandle(handle) ) : 1 ) )

///////////////////////////////////////////////////////////////////////////////
//
// closes a file handle
//
///////////////////////////////////////////////////////////////////////////////

#define CleanFileHandle(handle)                                         \
  ( ( ( handle != INVALID_HANDLE_VALUE) ?                               \
      ( CloseHandle(handle), handle = INVALID_HANDLE_VALUE, 1 ) : 1 ) )

#define CleanFileHandleOnErr(handle)                    \
  ( ( ( error ) ? ( CleanFileHandle(handle) ) : 1 ) )

#define CleanFileHandleOnCond(handle, cond)             \
  ( ( ( cond ) ? ( CleanFileHandle(handle) ) : 1 ) )

///////////////////////////////////////////////////////////////////////////////
//
// closes a lsa handle
//
///////////////////////////////////////////////////////////////////////////////

#define CleanLsaHandle(handle)                                          \
  ( ( ( handle ) ? ( LsaClose(handle), handle = NULL, 1 ) : 1 ) )

#define CleanLsaHandleOnErr(handle)                     \
  ( ( ( error ) ? ( CleanLsaHandle(handle) ) : 1 ) )

#define CleanLsaHandleOnCond(handle, cond)              \
  ( ( ( cond ) ? ( CleanLsaHandle(handle) ) : 1 ) )

///////////////////////////////////////////////////////////////////////////////
//
// frees a lsa buffer
//
///////////////////////////////////////////////////////////////////////////////

#define CleanLsaPtr(ptr)                                        \
  ( ( ( ptr ) ? ( LsaFreeMemory(ptr), ptr = NULL, 1 ) : 1 ) )

#define CleanLsaPtrOnErr(ptr)                   \
  ( ( ( error ) ? ( CleanLsaPtr(ptr) ) : 1 ) )

#define CleanLsaPtrOnCond(ptr, cond)            \
  ( ( ( cond ) ? ( CleanLsaPtr(ptr) ) : 1 ) )

///////////////////////////////////////////////////////////////////////////////
//
// closes a registry key
//
///////////////////////////////////////////////////////////////////////////////

#define CleanKey(key)                                           \
  ( ( ( key ) ? ( RegCloseKey(key), key = NULL, 1 ) : 1 ) )

#define CleanKeyOnErr(key)                      \
  ( ( ( error ) ? ( CleanKey(key) ) : 1 ) )

#define CleanKeyOnCond(key, cond)               \
  ( ( ( cond ) ? ( CleanKey(key) ) : 1 ) )

///////////////////////////////////////////////////////////////////////////////
//
// frees a sid
//
///////////////////////////////////////////////////////////////////////////////

#define CleanSid(sid)                                   \
  ( ( ( sid ) ? ( FreeSid(sid), sid = NULL, 1 ) : 1 ) )

#define CleanSidOnErr(sid)                      \
  ( ( ( error ) ? ( CleanSid(sid) ) : 1 ) )

#define CleanSidOnCond(sid, cond)               \
  ( ( ( cond ) ? ( CleanSid(sid) ) : 1 ) )

///////////////////////////////////////////////////////////////////////////////
//
// frees a buffer allocated by a lanman function
//
///////////////////////////////////////////////////////////////////////////////

#define CleanNetBuf(ptr)                                                \
  ( ( ( ptr ) ? ( NetApiBufferFree(ptr), ptr = NULL, 1 ) : 1 ) )

#define CleanNetBufOnErr(ptr)                   \
  ( ( ( error ) ? ( CleanNetBuf(ptr) ) : 1 ) )

#define CleanNetBufOnCond(ptr, cond)            \
  ( ( ( cond ) ? ( CleanNetBuf(ptr) ) : 1 ) )

///////////////////////////////////////////////////////////////////////////////
//
// frees a library handle
//
///////////////////////////////////////////////////////////////////////////////

#define CleanLibrary(lib)                                       \
  ( ( ( lib ) ? ( FreeLibrary(lib), lib = NULL, 1 ) : 1 ) )

#define CleanLibraryOnErr(lib)                  \
  ( ( ( error ) ? ( CleanLibrary(lib) ) : 1 ) )

#define CleanLibraryOnCond(lib, cond)           \
  ( ( ( cond ) ? ( CleanLibrary(lib) ) : 1 ) )

///////////////////////////////////////////////////////////////////////////////
//
// frees a pointer
//
///////////////////////////////////////////////////////////////////////////////

#define CleanPtr(ptr)                                   \
  ( ( ( ptr ) ? ( FreeMem(ptr), ptr = NULL, 1 ) : 1 ) )

#define CleanPtrOnErr(ptr)                      \
  ( ( ( error ) ? ( CleanPtr(ptr) ) : 1 ) )

#define CleanPtrOnCond(ptr, cond)               \
  ( ( ( cond ) ? ( CleanPtr(ptr) ) : 1 ) )


///////////////////////////////////////////////////////////////////////////////
//
// overwrites a buffer and frees the buffer pointer
//
///////////////////////////////////////////////////////////////////////////////

#define ZeroAndCleanPtr(ptr, size)                                      \
  ( ( ( ptr ) ? ( ZeroMemory(ptr, size), FreeMem(ptr), ptr = NULL, 1 ) : 1 ) )

#define ZeroAndCleanPtrOnErr(ptr, size)                         \
  ( ( ( error ) ? ( ZeroAndCleanPtr(ptr, size) ) : 1 ) )

#define ZeroAndCleanPtrOnCond(ptr, size, cond)          \
  ( ( ( cond ) ? ( ZeroAndCleanPtr(ptr, size) ) : 1 ) )

///////////////////////////////////////////////////////////////////////////////
//
// frees an array of pointers and the pointer itself
//
///////////////////////////////////////////////////////////////////////////////

#define CleanPtrs(ptr, size)                                            \
  ( ( ( ptr ) ? ( FreeArray((PVOID*)ptr, size), FreeMem(ptr), ptr = NULL, 1 ) : 1 ) )

#define CleanPtrsOnErr(ptr, size)                       \
  ( ( ( error ) ? ( CleanPtrs(ptr, size) ) : 1 ) )

#define CleanPtrsOnCond(ptr, size, cond)                \
  ( ( ( cond ) ? ( CleanPtrs(ptr, size) ) : 1 ) )

///////////////////////////////////////////////////////////////////////////////
//
// frees an array of pointers
//
///////////////////////////////////////////////////////////////////////////////

#define CleanArray(ptr, size)                                   \
  ( ( ( ptr ) ? ( FreeArray((PVOID*)ptr, size), 1 ) : 1 ) )

#define CleanArrayOnErr(ptr, size)                      \
  ( ( ( error ) ? ( CleanArray(ptr, size) ) : 1 ) )

#define CleanArrayOnCond(ptr, size, cond)               \
  ( ( ( cond ) ? ( CleanArray(ptr, size) ) : 1 ) )

///////////////////////////////////////////////////////////////////////////////
//
// frees a pointer allocated by SysAllocString
//
///////////////////////////////////////////////////////////////////////////////

#define CleanSysPtr(ptr)                                        \
  ( ( ( ptr ) ? ( SysFreeString(ptr), ptr = NULL, 1 ) : 1 ) )

#define CleanSysPtrOnErr(ptr)                   \
  ( ( ( error ) ? ( CleanSysPtr(ptr) ) : 1 ) )

#define CleanSysPtrOnCond(ptr, cond)            \
  ( ( ( cond ) ? ( CleanSysPtr(ptr) ) : 1 ) )


///////////////////////////////////////////////////////////////////////////////
//
// closes an eventlog handle
//
///////////////////////////////////////////////////////////////////////////////

#define CleanEventLog(handle)                                           \
  ( ( ( handle ) ? ( DeregisterEventSource(handle), handle = NULL, 1 ) : 1 ) )

#define CleanEventLogOnErr(handle)                      \
  ( ( ( error ) ? ( CleanEventLog(handle) ) : 1 ) )

#define CleanEventLogOnCond(handle, cond)               \
  ( ( ( cond ) ? ( CleanEventLog(handle) ) : 1 ) )

///////////////////////////////////////////////////////////////////////////////
//
// closes a service control manager or service handle
//
///////////////////////////////////////////////////////////////////////////////

#define CleanServiceHandle(handle)                                      \
  ( ( ( handle ) ? ( CloseServiceHandle(handle), handle = NULL, 1 ) : 1 ) )

#define CleanServiceHandleOnErr(handle)                         \
  ( ( ( error ) ? ( CleanServiceHandle(handle) ) : 1 ) )

#define CleanServiceHandleOnCond(handle, cond)          \
  ( ( ( cond ) ? ( CleanServiceHandle(handle) ) : 1 ) )

///////////////////////////////////////////////////////////////////////////////
//
// ends a thread
//
///////////////////////////////////////////////////////////////////////////////

#define CleanThread(thread, exit)                                       \
  ( ( ( thread ) ? ( TerminateThread(thread, exit), thread = NULL, 1 ) : 1 ) )

#define CleanThreadOnErr(thread, exit)                  \
  ( ( ( error ) ? ( CleanThread(thread, exit) ) : 1 ) )

#define CleanThreadOnCond(thread, exit, cond)           \
  ( ( ( cond ) ? ( CleanThread(thread, exit) ) : 1 ) )

///////////////////////////////////////////////////////////////////////////////
//
// ends a thread array
//
///////////////////////////////////////////////////////////////////////////////

#define CleanThreadArray(thread, exit, size)                            \
  { for(int count = 0; count < size; count++) CleanThread(thread[count], exit); \
    CleanPtr(thread); }

#define CleanThreadArrayOnErr(thread, exit, size)       \
  { if( error ) CleanThreadArray(thread, exit, size); }

#define CleanThreadArrayOnCond(thread, exit, size, cond)        \
  { if( cond ) CleanThreadArray(thread, exit, size); }

///////////////////////////////////////////////////////////////////////////////
//
// frees a buffer allocated by a terminal server function
//
///////////////////////////////////////////////////////////////////////////////

#define CleanWtsBuf(ptr)                                                \
  ( ( ( ptr && WTSFreeMemoryCall ) ? ( WTSFreeMemoryCall(ptr), ptr = NULL, 1 ) : 1 ) )

#define CleanWtsBufOnErr(ptr)                   \
  ( ( ( error ) ? ( CleanWtsBuf(ptr) ) : 1 ) )

#define CleanWtsBufOnCond(ptr)                  \
  ( ( ( cond ) ? ( CleanWtsBuf(ptr) ) : 1 ) )

///////////////////////////////////////////////////////////////////////////////
//
// closes an ip socket
//
///////////////////////////////////////////////////////////////////////////////

#define CleanSocket(sock)                                               \
  ( ( ( sock != INVALID_SOCKET ) ? ( shutdown(sock, SD_BOTH), sock = INVALID_SOCKET, 1 ) : 1 ) )

#define CleanSocketOnErr(sock)                  \
  ( ( ( error ) ? ( CleanSocket(sock) ) : 1 ) )

#define CleanSocketOnCond(sock)                 \
  ( ( ( cond ) ? ( CleanSocket(sock) ) : 1 ) )


///////////////////////////////////////////////////////////////////////////////
//
// returns the size of an array
//
///////////////////////////////////////////////////////////////////////////////

#define array_size(array) ( sizeof(array) / sizeof(array[0]) )


///////////////////////////////////////////////////////////////////////////////
//
// initializes, deletes, enters and leaves critical section objects
//
///////////////////////////////////////////////////////////////////////////////

#define CARE_INIT_CRIT_SECT(sect)                                       \
  ( !( (sect)->DebugInfo ) || IsBadCodePtr( (FARPROC) ( (sect)->DebugInfo ) )  ? \
    InitializeCriticalSection(sect) : (void)0 )

#define CARE_DEL_CRIT_SECT(sect)                                        \
  ( !IsBadCodePtr( (FARPROC) ( (sect)->DebugInfo ) ) ? DeleteCriticalSection(sect) : (void)0, \
    ZeroMemory( sect, sizeof(*sect) )  )

#define CARE_ENTER_CRIT_SECT(sect)                              \
  ( CARE_INIT_CRIT_SECT(sect), EnterCriticalSection(sect) )

#define CARE_TRY_ENTER_CRIT_SECT(sect)                          \
  ( CARE_INIT_CRIT_SECT(sect), TryEnterCriticalSection(sect) )

#define CARE_LEAVE_CRIT_SECT(sect)                                      \
  ( ( (sect)->DebugInfo ? 0 : InitializeCriticalSection(sect) ), LeaveCriticalSection(sect) )


#endif // #ifndef __MISC_H