#if !defined(RT_AUTOZERO_H)
#define RT_AUTOZERO_H

// autozero.h
//
// Description:
//  This file provides C++ classes that automatically initialize
//  Win32 API structures.
//
// Provides:
//  auto_zero_traits<T>
//                  Abstraction of name of T's size member.
//  auto_zero<T>    Initializes a structure with ZeroMemory()
//  auto_size<T>    As auto_zero<T>, but also sets T's size
//                  member to sizeof(T).
//
//  Specializations for common Win32 structures with size
//  members that must be properly initialized before being
//  passed to an API functin.  In order to provide these
//  specializations, this file must be included after the
//  corresponding Win32 header file that defines the structure.
//
// Example:
//
//    //----- Use the adapter's monitor handle to get the
//    // adapter's desktop extent in multiple monitor operations
//    rt::auto_size<MONITORINFOEX> info;
//    if (::GetMonitorInfo(d3d->GetAdapterMonitor(adapter), &info)) {
//      // do something with info
//    }
//
// Copyright (C) 2000-2001, Rich Thomson, all rights reserved.
//
namespace rt
{
    ////////////////////////////////////////////////////////////
    // auto_size_traits<T>
    //
    // Not every structure has the count member called dwSize
    // of type DWORD.  Some structures have cbSize declared as
    // a DWORD and others have cbSize declared as a UINT.
    //
    // The auto_size_traits helper class abstracts away this
    // dependency.  The default member describing the size of
    // the structure is dwSize.  Template specialization for
    // the structure type provides alternative definitions for
    // other structures.
    //
    template <typename T, typename R>
    class dwSize_traits
    {
    public:
        static R &size(T &item) { return item.dwSize; }
    };
    
    template <typename T, typename R>
    class cbSize_traits
    {
    public:
        static R &size(T &item) { return item.cbSize; }
    };
    
    // default traits are: "DWORD dwSize;"
    template <typename T>
    class auto_size_traits : public dwSize_traits<T, DWORD>
    {
    };
    
    ////////////////////////////////////////////////////////////
    // auto_zero<T>
    //
    // Initializes a structure to zero with ZeroMemory().
    //
    template <typename T>
    class auto_zero : public T
    {
    public:
        auto_zero() : T() { ZeroMemory(static_cast<T *>(this), sizeof(T)); }
        ~auto_zero() {}
    };
    
    ////////////////////////////////////////////////////////////
    // auto_size<T>
    //
    // Initialize a chunk of memory to zero and sets the size
    // member of T to sizeof(T).  Uses auto
    //
    // Example:
    //
    //    // dump out adapter's monitor geometry information
    //    rt::auto_size<MONITORINFOEX> info;
    //    if (GetMonitorInfo(d3d->GetAdapterMonitor(adapter), &info)) {
    //      // ...
    //    }
    //
    template <typename T, typename Tr = auto_size_traits<T> >
    class auto_size : public auto_zero<T>
    {
    public:
        auto_size() : auto_zero<T>()
        {
            Tr::size(static_cast<T &>(*this)) = sizeof(T);
        }
        ~auto_size() {}
    };
    
    
    // "DWORD cbSize;"
#define AZT_CB(T_) \
    template <> \
    class auto_size_traits<T_> : public cbSize_traits<T_, DWORD> { }
    
    // "UINT cbSize;"
#define AZT_CBU(Base_) \
    template <> \
    class auto_size_traits<Base_> : public cbSize_traits<Base_, UINT> { }
    
    ////////////////////////////////////////////////////////////
    // specializations for structures in win32 standard includes
    //
    // use include guards from .h files to avoid definint template
    // specializations for unused classes and avoid having to
    // include many .h files in order to obtain the specializations.
    //
    // This practice implies that autozero.h must be included after
    // any .h files that generate structures with specializations
    // listed here.
    //
#if defined(__IChannelMgr_INTERFACE_DEFINED__)
    AZT_CB(CHANNELSHORTCUTINFO);      // <chanmgr.h>
    AZT_CB(CHANNELCATEGORYINFO);
#endif
#if defined(_INC_COMMCTRL)
    AZT_CB(IMAGELISTDRAWPARAMS);      // <commctrl.h>
    AZT_CB(TBBUTTONINFO);
    AZT_CB(REBARINFO);
    AZT_CB(REBARBANDINFO);
    AZT_CB(TTTOOLINFO);
    AZT_CB(MCHITTESTINFO);
    AZT_CB(TRACKMOUSEEVENT);
#endif
#if defined(HLINK_H)
    AZT_CB(HLBWINFO);                 // <hlink.h>
#endif
#if defined(_HTTPEXT_H_)
    AZT_CB(EXTENSION_CONTROL_BLOCK);  // <httpext.h>
#endif
#if defined(_HTTPFILT_H_)
    AZT_CB(HTTP_FILTER_CONTEXT);      // <httpfilt.h>
#endif
#if defined(IMEMENUITEM_STRING_SIZE)
    AZT_CB(IMEMENUITEMINFO);          // <imm.h>
#endif
#if defined(__INTSHCUT_H__)
    AZT_CB(URLINVOKECOMMANDINFO);     // <intshcut.h>
#endif
#if defined(__javaexec_h__)
    AZT_CB(JAVAEXECUTEINFO);          // <javaexec.h>
#endif
#if defined(MSHTMHST_H)
    AZT_CB(DOCHOSTUIINFO);            // <mshtmhst.h>
#endif
#if defined(MSSIP_H)
    AZT_CB(SIP_SUBJECTINFO);          // <mssip.h>
    AZT_CB(SIP_DISPATCH_INFO);
#endif
#if defined(SM_CMONITORS)
    AZT_CB(MONITORINFO);              // <multimon.h>
    AZT_CB(MONITORINFOEX);
#endif
#if defined(_NATIVCOM_)
    AZT_CB(J2CMethodHookInfo);        // <nativcom.h>
    AZT_CB(C2JMethodHookInfo);
#endif
#if defined(__IQuickActivate_INTERFACE_DEFINED__)
    AZT_CB(QACONTAINER);              // <ocidl.h>
    AZT_CB(QACONTROL);
#endif
#if defined(__IOLETypes_INTERFACE_DEFINED__)
    AZT_CB(OBJECTDESCRIPTOR);         // <oleidl.h>
#endif
#if defined(_INC_PENWIN)
    AZT_CB(CTLINITHEDIT);             // <penwin.h>
    AZT_CB(CTLINITBEDIT);
    AZT_CB(PENTIP);
    AZT_CB(ANIMATEINFO);
    AZT_CB(CTLINITIEDIT);
    AZT_CB(PDEVENT);
    AZT_CB(STRKFMT);
    AZT_CB(PCMINFO);
    AZT_CB(INKINGINFO);
    AZT_CB(TARGINFO);
    AZT_CB(INPPARAMS);
#endif
#if defined(_RICHEDIT_)
    AZT_CB(CHARFORMAT);               // <richedit.h>
    AZT_CB(PARAFORMAT);
    AZT_CB(CHARFORMAT2);
    AZT_CB(PARAFORMAT2);
    AZT_CB(BIDIOPTIONS);
#endif
#if defined(RTFLIB_H)
    AZT_CB(LZFUHDR);                  // <rtflib.h>
#endif
#if defined(_INC_SETUPAPI)
    AZT_CB(SP_DEVINFO_DATA);          // <setupapi.h>
    AZT_CB(SP_DEVICE_INTERFACE_DATA);
    AZT_CB(SP_DEVICE_INTERFACE_DETAIL_DATA);
    AZT_CB(SP_DEVINFO_LIST_DETAIL_DATA);
    AZT_CB(SP_DEVINSTALL_PARAMS);
    AZT_CB(SP_CLASSINSTALL_HEADER);
    AZT_CB(SP_DRVINFO_DATA);
    AZT_CB(SP_DRVINFO_DETAIL_DATA);
    AZT_CB(SP_DRVINSTALL_PARAMS);
    AZT_CB(SP_CLASSIMAGELIST_DATA);
    AZT_CB(SP_PROPSHEETPAGE_REQUEST);
#endif
#if defined(_INC_SHELLAPI)
    AZT_CB(APPBARDATA);               // <shellapi.h>
    AZT_CB(SHELLEXECUTEINFO);
    AZT_CB(SHQUERYRBINFO);
    AZT_CB(NOTIFYICONDATA);
#endif
#if defined(_SHLOBJ_H_)
    AZT_CB(CMINVOKECOMMANDINFO);      // <shlobj.h>
    AZT_CB(CMINVOKECOMMANDINFOEX);
    AZT_CB(FVSHOWINFO);
    AZT_CB(SV2CVW2_PARAMS);
#endif
#if defined(_INC_SHLWAPI)
    AZT_CB(DLLVERSIONINFO);           // <shlwapi.h>
#endif
#if defined(__ISubscriptionMgr_INTERFACE_DEFINED__)
    AZT_CB(SUBSCRIPTIONINFO);
#endif
#if defined(__IEnumSTATURL_INTERFACE_DEFINED__)
    AZT_CB(STATURL);                  // <urlhist.h>
#endif
#if defined(__urlmon_h__)
    AZT_CB(BINDINFO);                 // <urlmon.h>
    AZT_CB(RemBINDINFO);
    AZT_CB(ZONEATTRIBUTES);
    AZT_CB(CODEBASEHOLD);
    AZT_CB(SOFTDISTINFO);
    AZT_CB(PROTOCOLFILTERDATA);
#endif
#if defined(_INC_VFW)
    AZT_CB(COMPVARS);                 // <vfw.h>
#endif
#if defined(_WABAPI_H_)
    AZT_CB(WAB_PARAM);                // <wabapi.h>
#endif
#if defined(_WINABLE_)
    AZT_CB(GUITHREADINFO);            // <winable.h>
#endif
#if defined(__WINCRYPT_H__)
    AZT_CB(CRYPT_OID_INFO);           // <wincrypt.h>
    AZT_CB(CMSG_SIGNER_ENCODE_INFO);
    AZT_CB(CMSG_SIGNED_ENCODE_INFO);
    AZT_CB(CMSG_ENVELOPED_ENCODE_INFO);
    AZT_CB(CMSG_SIGNED_AND_ENVELOPED_ENCODE_INFO);
    AZT_CB(CMSG_HASHED_ENCODE_INFO);
    AZT_CB(CMSG_ENCRYPTED_ENCODE_INFO);
    AZT_CB(CMSG_CTRL_DECRYPT_PARA);
    AZT_CB(CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA);
    AZT_CB(CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA);
    AZT_CB(CERT_KEY_CONTEXT);
    AZT_CB(CERT_STORE_PROV_INFO);
    AZT_CB(CTL_FIND_USAGE_PARA);
    AZT_CB(CTL_FIND_SUBJECT_PARA);
    AZT_CB(CTL_VERIFY_USAGE_PARA);
    AZT_CB(CTL_VERIFY_USAGE_STATUS);
    AZT_CB(CERT_REVOCATION_PARA);
    AZT_CB(CERT_REVOCATION_STATUS);
    AZT_CB(CRYPT_SIGN_MESSAGE_PARA);
    AZT_CB(CRYPT_VERIFY_MESSAGE_PARA);
    AZT_CB(CRYPT_ENCRYPT_MESSAGE_PARA);
    AZT_CB(CRYPT_DECRYPT_MESSAGE_PARA);
    AZT_CB(CRYPT_HASH_MESSAGE_PARA);
    AZT_CB(CRYPT_KEY_SIGN_MESSAGE_PARA);
    AZT_CB(CRYPT_KEY_VERIFY_MESSAGE_PARA);
#endif
#if defined(_WINGDI_)
    AZT_CB(DOCINFO);                  // <wingdi.h>
#endif
#if defined(_WINUSER_)
    AZT_CBU(WNDCLASSEX);              // <winuser.h>
    AZT_CBU(TPMPARAMS);
    AZT_CBU(MENUITEMINFO);
    AZT_CBU(DRAWTEXTPARAMS);
    AZT_CBU(HELPINFO);
    AZT_CBU(MSGBOXPARAMS);
    AZT_CBU(SCROLLINFO);
    AZT_CBU(NONCLIENTMETRICS);
    AZT_CBU(MINIMIZEDMETRICS);
    AZT_CBU(ICONMETRICS);
    AZT_CBU(ANIMATIONINFO);
    AZT_CBU(SERIALKEYS);
    AZT_CBU(HIGHCONTRAST);
    AZT_CBU(FILTERKEYS);
    AZT_CBU(STICKYKEYS);
    AZT_CBU(MOUSEKEYS);
    AZT_CBU(ACCESSTIMEOUT);
    AZT_CBU(SOUNDSENTRY);
    AZT_CBU(TOGGLEKEYS);
#if (_WIN32_WINNT >= 0x0400) && !defined(NOTRACKMOUSEEVENT)
    AZT_CBU(TRACKMOUSEEVENT);
#endif
#if (_WIN32_WINNT >= 0x0500)
    AZT_CBU(LASTINPUTINFO);
    AZT_CBU(MENUINFO);
    AZT_CBU(MONITORINFO);
    AZT_CBU(GUITHREADINFO);
    AZT_CBU(CURSORINFO);
    AZT_CBU(WINDOWINFO);
    AZT_CBU(TITLEBARINFO);
    AZT_CBU(MENUBARINFO);
    AZT_CBU(SCROLLBARINFO);
    AZT_CBU(COMBOBOXINFO);
    AZT_CBU(ALTTABINFO);
#endif
#endif
#if defined(_WINSOCK2SPI_)
    AZT_CB(NSP_ROUTINE);              // <ws2spi.h>
#endif
    
#undef AZT_CB
#undef AZT_CBU
    
};

#endif
