/*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Copyright (c) 2000 Microsoft Corporation Module Name: debug.cpp Abstract: Debug logging routines for W3spoof project. Author: Paul M Midgen (pmidge) 15-May-2000 Revision History: 15-May-2000 pmidge Created =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ #include "common.h" /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= MapIIDToString() WHAT : maps an IID to its string id. if the IID is unknown we emit a '?'. ARGS : hr - the IID code to map RETURNS : pointer to the IID's string name =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ LPSTR MapIIDToString(REFIID riid) { // // standard IIDs // CASE_IID(riid, IID_NULL); CASE_IID(riid, IID_IUnknown); CASE_IID(riid, IID_IClassFactory); CASE_IID(riid, IID_IDispatch); CASE_IID(riid, IID_IConnectionPointContainer); CASE_IID(riid, IID_IConnectionPoint); CASE_IID(riid, IID_IMarshal); CASE_IID(riid, IID_IStdMarshalInfo); CASE_IID(riid, IID_IExternalConnection); CASE_IID(riid, IID_IObjectWithSite); CASE_IID(riid, IID_IActiveScriptSite); CASE_IID(riid, IID_IProvideClassInfo); CASE_IID(riid, IID_IActiveScriptSiteInterruptPoll); CASE_IID(riid, IID_IActiveScriptSiteDebug); // CASE_IID(riid, IID_ICanHandleException); // dispex.h? // CASE_IID(riid, IID_IDispatchEx); // dispex.h? CASE_IID(riid, IID_IServiceProvider); // // app-defined IIDs // CASE_IID(riid, IID_IConfig); CASE_IID(riid, IID_IThreadPool); CASE_IID(riid, IID_IW3Spoof); CASE_IID(riid, IID_IW3SpoofClientSupport); CASE_IID(riid, IID_IW3SpoofEvents); CASE_IID(riid, IID_ISession); CASE_IID(riid, IID_ISocket); CASE_IID(riid, IID_IHeaders); CASE_IID(riid, IID_IEntity); CASE_IID(riid, IID_IUrl); CASE_IID(riid, IID_IRequest); CASE_IID(riid, IID_IResponse); CASE_IID(riid, IID_IW3SpoofRuntime); CASE_IID(riid, IID_IW3SpoofPropertyBag); CASE_IID(riid, IID_IW3SpoofFile); return "?"; } LPSTR MapIOTYPEToString(IOTYPE iot) { switch(iot) { CASE_OF(IOCT_CONNECT); CASE_OF(IOCT_RECV); CASE_OF(IOCT_SEND); CASE_OF(IOCT_DUMMY); default : return "?"; } } LPSTR MapScriptDispidToString(SCRIPTDISPID sd) { switch(sd) { CASE_OF(Global); CASE_OF(OnConnect); CASE_OF(OnDataAvailable); CASE_OF(OnRequest); CASE_OF(OnResponse); CASE_OF(OnClose); default : return "?"; } } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= MapHResultToString() WHAT : maps an HRESULT to its string id. if the HRESULT is unknown we emit a '?'. ARGS : hr - the HRESULT code to map RETURNS : pointer to the HRESULT's string name =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ LPSTR MapHResultToString(HRESULT hr) { switch(hr) { CASE_OF(S_OK); CASE_OF(E_NOINTERFACE); CASE_OF(E_POINTER); CASE_OF(E_UNEXPECTED); CASE_OF(E_INVALIDARG); CASE_OF(E_OUTOFMEMORY); CASE_OF(E_FAIL); CASE_OF(E_NOTIMPL); CASE_OF(E_PENDING); CASE_OF(E_ACCESSDENIED); CASE_OF(CLASS_E_NOAGGREGATION); CASE_OF(TYPE_E_IOERROR); CASE_OF(TYPE_E_REGISTRYACCESS); CASE_OF(TYPE_E_INVALIDSTATE); CASE_OF(TYPE_E_BUFFERTOOSMALL); CASE_OF(TYPE_E_FIELDNOTFOUND); CASE_OF(TYPE_E_ELEMENTNOTFOUND); CASE_OF(TYPE_E_AMBIGUOUSNAME); CASE_OF(TYPE_E_UNKNOWNLCID); CASE_OF(TYPE_E_BADMODULEKIND); CASE_OF(TYPE_E_CANTLOADLIBRARY); CASE_OF(TYPE_E_INCONSISTENTPROPFUNCS); CASE_OF(CONNECT_E_NOCONNECTION); CASE_OF(CONNECT_E_ADVISELIMIT); CASE_OF(CO_E_OBJNOTREG); CASE_OF(DISP_E_BADPARAMCOUNT); CASE_OF(DISP_E_BADVARTYPE); CASE_OF(DISP_E_EXCEPTION); CASE_OF(DISP_E_MEMBERNOTFOUND); CASE_OF(DISP_E_NONAMEDARGS); CASE_OF(DISP_E_OVERFLOW); CASE_OF(DISP_E_PARAMNOTFOUND); CASE_OF(DISP_E_TYPEMISMATCH); CASE_OF(DISP_E_UNKNOWNINTERFACE); CASE_OF(DISP_E_UNKNOWNLCID); CASE_OF(DISP_E_PARAMNOTOPTIONAL); CASE_OF(DISP_E_UNKNOWNNAME); default : return "?"; } } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= MapStateToString() WHAT : maps a STATE value to a string. if the state is unknown we emit a '?'. ARGS : st - the STATE to map RETURNS : pointer to the STATE's string name =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ LPSTR MapStateToString(STATE st) { switch(st) { CASE_OF(ST_CREATED); CASE_OF(ST_OPENING); CASE_OF(ST_OPEN); CASE_OF(ST_CLOSING); CASE_OF(ST_CLOSED); CASE_OF(ST_ERROR); default : return "?"; } } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= MapIoStateToString() WHAT : maps a SERVERSTATE value to a string. if the state is unknown we emit a '?'. ARGS : st - the SERVERSTATE to map RETURNS : pointer to the SERVERSTATE's string name =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ LPSTR MapStateToString(SERVERSTATE st) { switch(st) { CASE_OF(SS_START_STATE); CASE_OF(SS_SOCKET_CONNECTED); CASE_OF(SS_REQUEST_PENDING); CASE_OF(SS_REQUEST_COMPLETE); CASE_OF(SS_RESPONSE_PENDING); CASE_OF(SS_RESPONSE_COMPLETE); CASE_OF(SS_SOCKET_DISCONNECTED); default : return "?"; } } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= MapStateToString() WHAT : maps a script engine state to a string for the log file. ARGS : st - the state RETURNS : string representation of the state =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ LPSTR MapStateToString(SCRIPTSTATE st) { switch(st) { CASE_OF(SCRIPTSTATE_UNINITIALIZED); CASE_OF(SCRIPTSTATE_INITIALIZED); CASE_OF(SCRIPTSTATE_STARTED); CASE_OF(SCRIPTSTATE_CONNECTED); CASE_OF(SCRIPTSTATE_DISCONNECTED); CASE_OF(SCRIPTSTATE_CLOSED); default : return "?"; } } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= MapTPOToString() WHAT : maps a TPO_* (thread pool option) value to a string. if the option is unknown we emit a '?'. ARGS : option - the option to map RETURNS : pointer to the options's string name =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ LPSTR MapTPOToString(DWORD option) { switch(option) { CASE_OF(TPO_MAX_POOL_THREADS); CASE_OF(TPO_MAX_ACTIVE_THREADS); CASE_OF(TPO_SERVER_LISTEN_PORT); default : return "?"; } } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= MapErrorToString() WHAT : maps an error code to its string id. if the error is unknown we emit a '?'. ARGS : error - the error code to map RETURNS : pointer to the error code's string name =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ LPSTR MapErrorToString(int error) { switch(error) { CASE_OF(ERROR_SUCCESS); CASE_OF(ERROR_INVALID_FUNCTION); CASE_OF(ERROR_FILE_NOT_FOUND); CASE_OF(ERROR_PATH_NOT_FOUND); CASE_OF(ERROR_TOO_MANY_OPEN_FILES); CASE_OF(ERROR_ACCESS_DENIED); CASE_OF(ERROR_INVALID_HANDLE); CASE_OF(ERROR_ARENA_TRASHED); CASE_OF(ERROR_NOT_ENOUGH_MEMORY); CASE_OF(ERROR_INVALID_BLOCK); CASE_OF(ERROR_BAD_ENVIRONMENT); CASE_OF(ERROR_BAD_FORMAT); CASE_OF(ERROR_INVALID_ACCESS); CASE_OF(ERROR_INVALID_DATA); CASE_OF(ERROR_OUTOFMEMORY); CASE_OF(ERROR_INVALID_DRIVE); CASE_OF(ERROR_CURRENT_DIRECTORY); CASE_OF(ERROR_NOT_SAME_DEVICE); CASE_OF(ERROR_NO_MORE_FILES); CASE_OF(ERROR_WRITE_PROTECT); CASE_OF(ERROR_BAD_UNIT); CASE_OF(ERROR_NOT_READY); CASE_OF(ERROR_BAD_COMMAND); CASE_OF(ERROR_CRC); CASE_OF(ERROR_BAD_LENGTH); CASE_OF(ERROR_SEEK); CASE_OF(ERROR_NOT_DOS_DISK); CASE_OF(ERROR_SECTOR_NOT_FOUND); CASE_OF(ERROR_OUT_OF_PAPER); CASE_OF(ERROR_WRITE_FAULT); CASE_OF(ERROR_READ_FAULT); CASE_OF(ERROR_GEN_FAILURE); CASE_OF(ERROR_SHARING_VIOLATION); CASE_OF(ERROR_LOCK_VIOLATION); CASE_OF(ERROR_WRONG_DISK); CASE_OF(ERROR_SHARING_BUFFER_EXCEEDED); CASE_OF(ERROR_HANDLE_EOF); CASE_OF(ERROR_HANDLE_DISK_FULL); CASE_OF(ERROR_NOT_SUPPORTED); CASE_OF(ERROR_REM_NOT_LIST); CASE_OF(ERROR_DUP_NAME); CASE_OF(ERROR_BAD_NETPATH); CASE_OF(ERROR_NETWORK_BUSY); CASE_OF(ERROR_DEV_NOT_EXIST); CASE_OF(ERROR_TOO_MANY_CMDS); CASE_OF(ERROR_ADAP_HDW_ERR); CASE_OF(ERROR_BAD_NET_RESP); CASE_OF(ERROR_UNEXP_NET_ERR); CASE_OF(ERROR_BAD_REM_ADAP); CASE_OF(ERROR_PRINTQ_FULL); CASE_OF(ERROR_NO_SPOOL_SPACE); CASE_OF(ERROR_PRINT_CANCELLED); CASE_OF(ERROR_NETNAME_DELETED); CASE_OF(ERROR_NETWORK_ACCESS_DENIED); CASE_OF(ERROR_BAD_DEV_TYPE); CASE_OF(ERROR_BAD_NET_NAME); CASE_OF(ERROR_TOO_MANY_NAMES); CASE_OF(ERROR_TOO_MANY_SESS); CASE_OF(ERROR_SHARING_PAUSED); CASE_OF(ERROR_REQ_NOT_ACCEP); CASE_OF(ERROR_REDIR_PAUSED); CASE_OF(ERROR_FILE_EXISTS); CASE_OF(ERROR_CANNOT_MAKE); CASE_OF(ERROR_FAIL_I24); CASE_OF(ERROR_OUT_OF_STRUCTURES); CASE_OF(ERROR_ALREADY_ASSIGNED); CASE_OF(ERROR_INVALID_PASSWORD); CASE_OF(ERROR_INVALID_PARAMETER); CASE_OF(ERROR_NET_WRITE_FAULT); CASE_OF(ERROR_NO_PROC_SLOTS); CASE_OF(ERROR_TOO_MANY_SEMAPHORES); CASE_OF(ERROR_EXCL_SEM_ALREADY_OWNED); CASE_OF(ERROR_SEM_IS_SET); CASE_OF(ERROR_TOO_MANY_SEM_REQUESTS); CASE_OF(ERROR_INVALID_AT_INTERRUPT_TIME); CASE_OF(ERROR_SEM_OWNER_DIED); CASE_OF(ERROR_SEM_USER_LIMIT); CASE_OF(ERROR_DISK_CHANGE); CASE_OF(ERROR_DRIVE_LOCKED); CASE_OF(ERROR_BROKEN_PIPE); CASE_OF(ERROR_OPEN_FAILED); CASE_OF(ERROR_BUFFER_OVERFLOW); CASE_OF(ERROR_DISK_FULL); CASE_OF(ERROR_NO_MORE_SEARCH_HANDLES); CASE_OF(ERROR_INVALID_TARGET_HANDLE); CASE_OF(ERROR_INVALID_CATEGORY); CASE_OF(ERROR_INVALID_VERIFY_SWITCH); CASE_OF(ERROR_BAD_DRIVER_LEVEL); CASE_OF(ERROR_CALL_NOT_IMPLEMENTED); CASE_OF(ERROR_SEM_TIMEOUT); CASE_OF(ERROR_INSUFFICIENT_BUFFER); CASE_OF(ERROR_INVALID_NAME); CASE_OF(ERROR_INVALID_LEVEL); CASE_OF(ERROR_NO_VOLUME_LABEL); CASE_OF(ERROR_MOD_NOT_FOUND); CASE_OF(ERROR_PROC_NOT_FOUND); CASE_OF(ERROR_WAIT_NO_CHILDREN); CASE_OF(ERROR_CHILD_NOT_COMPLETE); CASE_OF(ERROR_DIRECT_ACCESS_HANDLE); CASE_OF(ERROR_NEGATIVE_SEEK); CASE_OF(ERROR_SEEK_ON_DEVICE); CASE_OF(ERROR_DIR_NOT_ROOT); CASE_OF(ERROR_DIR_NOT_EMPTY); CASE_OF(ERROR_PATH_BUSY); CASE_OF(ERROR_SYSTEM_TRACE); CASE_OF(ERROR_INVALID_EVENT_COUNT); CASE_OF(ERROR_TOO_MANY_MUXWAITERS); CASE_OF(ERROR_INVALID_LIST_FORMAT); CASE_OF(ERROR_BAD_ARGUMENTS); CASE_OF(ERROR_BAD_PATHNAME); CASE_OF(ERROR_BUSY); CASE_OF(ERROR_CANCEL_VIOLATION); CASE_OF(ERROR_ALREADY_EXISTS); CASE_OF(ERROR_FILENAME_EXCED_RANGE); CASE_OF(ERROR_LOCKED); CASE_OF(ERROR_NESTING_NOT_ALLOWED); CASE_OF(ERROR_BAD_PIPE); CASE_OF(ERROR_PIPE_BUSY); CASE_OF(ERROR_NO_DATA); CASE_OF(ERROR_PIPE_NOT_CONNECTED); CASE_OF(ERROR_MORE_DATA); CASE_OF(ERROR_NO_MORE_ITEMS); CASE_OF(ERROR_NOT_OWNER); CASE_OF(ERROR_PARTIAL_COPY); CASE_OF(ERROR_MR_MID_NOT_FOUND); CASE_OF(ERROR_INVALID_ADDRESS); CASE_OF(ERROR_PIPE_CONNECTED); CASE_OF(ERROR_PIPE_LISTENING); CASE_OF(ERROR_OPERATION_ABORTED); CASE_OF(ERROR_IO_INCOMPLETE); CASE_OF(ERROR_IO_PENDING); CASE_OF(ERROR_NOACCESS); CASE_OF(ERROR_STACK_OVERFLOW); CASE_OF(ERROR_INVALID_FLAGS); CASE_OF(ERROR_NO_TOKEN); CASE_OF(ERROR_BADDB); CASE_OF(ERROR_BADKEY); CASE_OF(ERROR_CANTOPEN); CASE_OF(ERROR_CANTREAD); CASE_OF(ERROR_CANTWRITE); CASE_OF(ERROR_REGISTRY_RECOVERED); CASE_OF(ERROR_REGISTRY_CORRUPT); CASE_OF(ERROR_REGISTRY_IO_FAILED); CASE_OF(ERROR_NOT_REGISTRY_FILE); CASE_OF(ERROR_KEY_DELETED); CASE_OF(ERROR_CIRCULAR_DEPENDENCY); CASE_OF(ERROR_SERVICE_NOT_ACTIVE); CASE_OF(ERROR_DLL_INIT_FAILED); CASE_OF(ERROR_CANCELLED); CASE_OF(ERROR_BAD_USERNAME); CASE_OF(ERROR_LOGON_FAILURE); CASE_OF(WAIT_FAILED); CASE_OF(WAIT_TIMEOUT); CASE_OF(WAIT_IO_COMPLETION); CASE_OF(RPC_S_INVALID_STRING_BINDING); CASE_OF(RPC_S_WRONG_KIND_OF_BINDING); CASE_OF(RPC_S_INVALID_BINDING); CASE_OF(RPC_S_PROTSEQ_NOT_SUPPORTED); CASE_OF(RPC_S_INVALID_RPC_PROTSEQ); CASE_OF(RPC_S_INVALID_STRING_UUID); CASE_OF(RPC_S_INVALID_ENDPOINT_FORMAT); CASE_OF(RPC_S_INVALID_NET_ADDR); CASE_OF(RPC_S_NO_ENDPOINT_FOUND); CASE_OF(RPC_S_INVALID_TIMEOUT); CASE_OF(RPC_S_OBJECT_NOT_FOUND); CASE_OF(RPC_S_ALREADY_REGISTERED); CASE_OF(RPC_S_TYPE_ALREADY_REGISTERED); CASE_OF(RPC_S_ALREADY_LISTENING); CASE_OF(RPC_S_NO_PROTSEQS_REGISTERED); CASE_OF(RPC_S_NOT_LISTENING); CASE_OF(RPC_S_UNKNOWN_MGR_TYPE); CASE_OF(RPC_S_UNKNOWN_IF); CASE_OF(RPC_S_NO_BINDINGS); CASE_OF(RPC_S_NO_PROTSEQS); CASE_OF(RPC_S_CANT_CREATE_ENDPOINT); CASE_OF(RPC_S_OUT_OF_RESOURCES); CASE_OF(RPC_S_SERVER_UNAVAILABLE); CASE_OF(RPC_S_SERVER_TOO_BUSY); CASE_OF(RPC_S_INVALID_NETWORK_OPTIONS); CASE_OF(RPC_S_NO_CALL_ACTIVE); CASE_OF(RPC_S_CALL_FAILED); CASE_OF(RPC_S_CALL_FAILED_DNE); CASE_OF(RPC_S_PROTOCOL_ERROR); CASE_OF(RPC_S_UNSUPPORTED_TRANS_SYN); CASE_OF(RPC_S_UNSUPPORTED_TYPE); CASE_OF(RPC_S_INVALID_TAG); CASE_OF(RPC_S_INVALID_BOUND); CASE_OF(RPC_S_NO_ENTRY_NAME); CASE_OF(RPC_S_INVALID_NAME_SYNTAX); CASE_OF(RPC_S_UNSUPPORTED_NAME_SYNTAX); CASE_OF(RPC_S_UUID_NO_ADDRESS); CASE_OF(RPC_S_DUPLICATE_ENDPOINT); CASE_OF(RPC_S_UNKNOWN_AUTHN_TYPE); CASE_OF(RPC_S_MAX_CALLS_TOO_SMALL); CASE_OF(RPC_S_STRING_TOO_LONG); CASE_OF(RPC_S_PROTSEQ_NOT_FOUND); CASE_OF(RPC_S_PROCNUM_OUT_OF_RANGE); CASE_OF(RPC_S_BINDING_HAS_NO_AUTH); CASE_OF(RPC_S_UNKNOWN_AUTHN_SERVICE); CASE_OF(RPC_S_UNKNOWN_AUTHN_LEVEL); CASE_OF(RPC_S_INVALID_AUTH_IDENTITY); CASE_OF(RPC_S_UNKNOWN_AUTHZ_SERVICE); CASE_OF(EPT_S_INVALID_ENTRY); CASE_OF(EPT_S_CANT_PERFORM_OP); CASE_OF(EPT_S_NOT_REGISTERED); CASE_OF(RPC_S_NOTHING_TO_EXPORT); CASE_OF(RPC_S_INCOMPLETE_NAME); CASE_OF(RPC_S_INVALID_VERS_OPTION); CASE_OF(RPC_S_NO_MORE_MEMBERS); CASE_OF(RPC_S_NOT_ALL_OBJS_UNEXPORTED); CASE_OF(RPC_S_INTERFACE_NOT_FOUND); CASE_OF(RPC_S_ENTRY_ALREADY_EXISTS); CASE_OF(RPC_S_ENTRY_NOT_FOUND); CASE_OF(RPC_S_NAME_SERVICE_UNAVAILABLE); CASE_OF(RPC_S_INVALID_NAF_ID); CASE_OF(RPC_S_CANNOT_SUPPORT); CASE_OF(RPC_S_NO_CONTEXT_AVAILABLE); CASE_OF(RPC_S_INTERNAL_ERROR); CASE_OF(RPC_S_ZERO_DIVIDE); CASE_OF(RPC_S_ADDRESS_ERROR); CASE_OF(RPC_S_FP_DIV_ZERO); CASE_OF(RPC_S_FP_UNDERFLOW); CASE_OF(RPC_S_FP_OVERFLOW); CASE_OF(RPC_X_NO_MORE_ENTRIES); CASE_OF(RPC_X_SS_CHAR_TRANS_OPEN_FAIL); CASE_OF(RPC_X_SS_CHAR_TRANS_SHORT_FILE); CASE_OF(RPC_X_SS_IN_NULL_CONTEXT); CASE_OF(RPC_X_SS_CONTEXT_DAMAGED); CASE_OF(RPC_X_SS_HANDLES_MISMATCH); CASE_OF(RPC_X_SS_CANNOT_GET_CALL_HANDLE); CASE_OF(RPC_X_NULL_REF_POINTER); CASE_OF(RPC_X_ENUM_VALUE_OUT_OF_RANGE); CASE_OF(RPC_X_BYTE_COUNT_TOO_SMALL); CASE_OF(RPC_X_BAD_STUB_DATA); CASE_OF(WSAEINTR); CASE_OF(WSAEBADF); CASE_OF(WSAEACCES); CASE_OF(WSAEFAULT); CASE_OF(WSAEINVAL); CASE_OF(WSAEMFILE); CASE_OF(WSAEWOULDBLOCK); CASE_OF(WSAEINPROGRESS); CASE_OF(WSAEALREADY); CASE_OF(WSAENOTSOCK); CASE_OF(WSAEDESTADDRREQ); CASE_OF(WSAEMSGSIZE); CASE_OF(WSAEPROTOTYPE); CASE_OF(WSAENOPROTOOPT); CASE_OF(WSAEPROTONOSUPPORT); CASE_OF(WSAESOCKTNOSUPPORT); CASE_OF(WSAEOPNOTSUPP); CASE_OF(WSAEPFNOSUPPORT); CASE_OF(WSAEAFNOSUPPORT); CASE_OF(WSAEADDRINUSE); CASE_OF(WSAEADDRNOTAVAIL); CASE_OF(WSAENETDOWN); CASE_OF(WSAENETUNREACH); CASE_OF(WSAENETRESET); CASE_OF(WSAECONNABORTED); CASE_OF(WSAECONNRESET); CASE_OF(WSAENOBUFS); CASE_OF(WSAEISCONN); CASE_OF(WSAENOTCONN); CASE_OF(WSAESHUTDOWN); CASE_OF(WSAETOOMANYREFS); CASE_OF(WSAETIMEDOUT); CASE_OF(WSAECONNREFUSED); CASE_OF(WSAELOOP); CASE_OF(WSAENAMETOOLONG); CASE_OF(WSAEHOSTDOWN); CASE_OF(WSAEHOSTUNREACH); CASE_OF(WSAENOTEMPTY); CASE_OF(WSAEPROCLIM); CASE_OF(WSAEUSERS); CASE_OF(WSAEDQUOT); CASE_OF(WSAESTALE); CASE_OF(WSAEREMOTE); CASE_OF(WSAEDISCON); CASE_OF(WSASYSNOTREADY); CASE_OF(WSAVERNOTSUPPORTED); CASE_OF(WSANOTINITIALISED); CASE_OF(WSAHOST_NOT_FOUND); CASE_OF(WSATRY_AGAIN); CASE_OF(WSANO_RECOVERY); CASE_OF(WSANO_DATA); CASE_OF(ERROR_FAILURE); CASE_OF(ERROR_INVALID_STATE); default : return "?"; } } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= MapDispidToString() WHAT : maps a dispid to a string for the log file. ARGS : dispid - the dispid RETURNS : string representation of the dispid =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ LPSTR MapDispidToString(DISPID dispid) { switch(dispid) { // special dispids CASE_OF(DISPID_VALUE); CASE_OF(DISPID_NEWENUM); CASE_OF(DISPID_EVALUATE); CASE_OF(DISPID_PROPERTYPUT); CASE_OF(DISPID_CONSTRUCTOR); CASE_OF(DISPID_DESTRUCTOR); CASE_OF(DISPID_UNKNOWN); CASE_OF(DISPID_COLLECT); // internal OM dispids CASE_OF(DISPID_SESSION_SOCKET); CASE_OF(DISPID_SESSION_REQUEST); CASE_OF(DISPID_SESSION_RESPONSE); CASE_OF(DISPID_SESSION_GETPROPERTYBAG); CASE_OF(DISPID_SESSION_KEEPALIVE); CASE_OF(DISPID_SOCKET_PARENT); CASE_OF(DISPID_SOCKET_SEND); CASE_OF(DISPID_SOCKET_RECV); CASE_OF(DISPID_SOCKET_OPTION); CASE_OF(DISPID_SOCKET_CLOSE); CASE_OF(DISPID_SOCKET_RESOLVE); CASE_OF(DISPID_SOCKET_LOCALNAME); CASE_OF(DISPID_SOCKET_LOCALADDRESS); CASE_OF(DISPID_SOCKET_LOCALPORT); CASE_OF(DISPID_SOCKET_REMOTENAME); CASE_OF(DISPID_SOCKET_REMOTEADDRESS); CASE_OF(DISPID_SOCKET_REMOTEPORT); CASE_OF(DISPID_HEADERS_PARENT); CASE_OF(DISPID_HEADERS_GET); CASE_OF(DISPID_HEADERS_SET); CASE_OF(DISPID_HEADERS_GETHEADER); CASE_OF(DISPID_HEADERS_SETHEADER); CASE_OF(DISPID_ENTITY_PARENT); CASE_OF(DISPID_ENTITY_GET); CASE_OF(DISPID_ENTITY_SET); CASE_OF(DISPID_ENTITY_COMPRESS); CASE_OF(DISPID_ENTITY_DECOMPRESS); CASE_OF(DISPID_URL_PARENT); CASE_OF(DISPID_URL_ENCODING); CASE_OF(DISPID_URL_SCHEME); CASE_OF(DISPID_URL_SERVER); CASE_OF(DISPID_URL_PORT); CASE_OF(DISPID_URL_PATH); CASE_OF(DISPID_URL_RESOURCE); CASE_OF(DISPID_URL_QUERY); CASE_OF(DISPID_URL_FRAGMENT); CASE_OF(DISPID_URL_ESCAPE); CASE_OF(DISPID_URL_UNESCAPE); CASE_OF(DISPID_URL_SET); CASE_OF(DISPID_URL_GET); CASE_OF(DISPID_REQUEST_PARENT); CASE_OF(DISPID_REQUEST_HEADERS); CASE_OF(DISPID_REQUEST_ENTITY); CASE_OF(DISPID_REQUEST_URL); CASE_OF(DISPID_REQUEST_VERB); CASE_OF(DISPID_REQUEST_HTTPVERSION); CASE_OF(DISPID_RESPONSE_PARENT); CASE_OF(DISPID_RESPONSE_HEADERS); CASE_OF(DISPID_RESPONSE_ENTITY); CASE_OF(DISPID_RESPONSE_STATUSCODE); CASE_OF(DISPID_RESPONSE_STATUSTEXT); CASE_OF(DISPID_W3SPOOF_REGISTERCLIENT); CASE_OF(DISPID_W3SPOOF_REVOKECLIENT); // internal runtime dispids CASE_OF(DISPID_RUNTIME_GETFILE); CASE_OF(DISPID_FILE_OPEN); CASE_OF(DISPID_FILE_CLOSE); CASE_OF(DISPID_FILE_WRITE); CASE_OF(DISPID_FILE_WRITELINE); CASE_OF(DISPID_FILE_WRITEBLANKLINE); CASE_OF(DISPID_FILE_READ); CASE_OF(DISPID_FILE_READALL); CASE_OF(DISPID_FILE_ATTRIBUTES); CASE_OF(DISPID_FILE_SIZE); CASE_OF(DISPID_FILE_TYPE); CASE_OF(DISPID_FILE_DATELASTMODIFIED); CASE_OF(DISPID_PROPERTYBAG_GET); CASE_OF(DISPID_PROPERTYBAG_SET); CASE_OF(DISPID_PROPERTYBAG_EXPIRES); CASE_OF(DISPID_PROPERTYBAG_FLUSH); default : return "?"; } } LPSTR MapVariantTypeToString(VARIANT* pvar) { if( pvar ) { switch( V_VT(pvar) ) { CASE_OF(VT_ARRAY | VT_UI1); CASE_OF(VT_EMPTY); CASE_OF(VT_NULL); CASE_OF(VT_I2); CASE_OF(VT_I4); CASE_OF(VT_R4); CASE_OF(VT_R8); CASE_OF(VT_CY); CASE_OF(VT_DATE); CASE_OF(VT_BSTR); CASE_OF(VT_DISPATCH); CASE_OF(VT_ERROR); CASE_OF(VT_BOOL); CASE_OF(VT_VARIANT); CASE_OF(VT_DECIMAL); CASE_OF(VT_RECORD); CASE_OF(VT_UNKNOWN); CASE_OF(VT_I1); CASE_OF(VT_UI1); CASE_OF(VT_UI2); CASE_OF(VT_UI4); CASE_OF(VT_INT); CASE_OF(VT_UINT); CASE_OF(VT_ARRAY); CASE_OF(VT_BYREF); default : return "?"; } } else { return "?"; } } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= MapInvokeFlagsToString() WHAT : maps invoke flags to a string for the log file. ARGS : flags - the invoke flags RETURNS : string representation of the flags =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ LPSTR MapInvokeFlagsToString(WORD flags) { return "NOT_IMPLEMENTED"; } #ifdef _DEBUG #define DEBUG_DEFAULT_DBGFILE L"W3SPOOF.LOG" #define DEBUG_LOGFILE_MUTEX L"W3Spoof_LogFile_Mutex" // // globals // DWORD g_dwTlsIndex = 0L; DWORD g_dwDebugFlags = DBG_NO_DEBUG; HANDLE g_hDebugLogFile = NULL; HANDLE g_mtxDebugLogFile = NULL; LPCWSTR g_wszDebugFlags = L"debugflags"; MEMUSAGE g_memusage = {0}; /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= DebugInitialize() WHAT : initializes the debugging support for the application. allocates thread-local storage and opens a log file if necessary. on failure, the function sets the DBG_NO_DEBUG flag so other debug functions won't do anything to get us in trouble. ARGS : none RETURNS : nothing =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ void DebugInitialize( void ) { LPDWORD pdw = NULL; DebugMemInitialize(); if( GetRegValue(g_wszDebugFlags, REG_DWORD, (void**) &pdw) ) { g_dwDebugFlags = *pdw; delete pdw; } else { g_dwDebugFlags = DEBUG_DEFAULT_FLAGS; } if( DBG_THROWDBGALERT & g_dwDebugFlags ) DebugThrowDbgAlert(); if( !(g_dwDebugFlags & DBG_NO_DEBUG) ) { // // allocate a TLS slot or else we can't // do call tracing // if( (g_dwTlsIndex = TlsAlloc()) == 0xFFFFFFFF ) goto no_debug; // // if logging to file is enabled, open the log file // and create a mutex for log dumps, disable debug // logging on error // if( g_dwDebugFlags & DBG_TO_FILE ) { if( !( _opendebugfile() && (g_mtxDebugLogFile = CreateMutex(NULL, FALSE, DEBUG_LOGFILE_MUTEX)) ) ) goto no_debug; } // // print the log banner // char* time = _gettimestamp(); _debugout( NULL, TRUE, FALSE, "\r\nDebug W3SPOOF.EXE started at %s with flags: %x\r\n\r\n", time, g_dwDebugFlags ); delete [] time; return; } else { DebugMemTerminate(); } no_debug: g_dwDebugFlags = DBG_NO_DEBUG; } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= DebugTerminate() WHAT : terminates debugging support for the application. ARGS : none RETURNS : nothing. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ void DebugTerminate( void ) { if( !(g_dwDebugFlags & DBG_NO_DEBUG) ) { DebugMemTerminate(); if( g_dwTlsIndex ) TlsFree(g_dwTlsIndex); if( (g_dwDebugFlags & DBG_TO_FILE) && g_hDebugLogFile ) { _closedebugfile(); CloseHandle(g_mtxDebugLogFile); g_mtxDebugLogFile = NULL; } } } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= DebugMemInitialize() WHAT : Initializes memory allocation tracking for the app. ARGS : none. RETURNS : nothing. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ void DebugMemInitialize(void) { InitializeCriticalSection(&g_memusage.lock); g_memusage.total = 0; } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= DebugMemTerminate() WHAT : Terminates memory allocation tracking and prints the final line in the logfile indicating how many bytes of memory were unallocated at process termination. ARGS : none. RETURNS : nothing. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ void DebugMemTerminate(void) { if( g_dwDebugFlags & DBG_MEM ) DebugTrace("*** unallocated memory: %d bytes", g_memusage.total); DeleteCriticalSection(&g_memusage.lock); } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= DebugMemAlloc() WHAT : Increments our allocation tracking value by the number of bytes a given allocation maps to on the process heap. ARGS : pv - pointer to allocated memory. RETURNS : nothing. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ void DebugMemAlloc(void* pv) { EnterCriticalSection(&g_memusage.lock); g_memusage.total += HeapSize(GetProcessHeap(), 0, pv); LeaveCriticalSection(&g_memusage.lock); } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= DebugMemFree() WHAT : Decrements our allocation tracking value by the number of bytes an allocation uses on the heap. ARGS : pv - pointer to allocated memory. RETURNS : nothing. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ void DebugMemFree(void* pv) { EnterCriticalSection(&g_memusage.lock); g_memusage.total -= HeapSize(GetProcessHeap(), 0, pv); LeaveCriticalSection(&g_memusage.lock); } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= DebugThrowDbgAlert() WHAT : Throws an alert dialog displaying the process PID so a debugger can be attached. ARGS : none. RETURNS : nothing. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ void DebugThrowDbgAlert(void) { char buf[256]; wsprintfA( buf, "pid=%d", GetCurrentProcessId() ); MessageBoxA(NULL, buf, "Attach Debugger!", MB_OK | MB_ICONSTOP | MB_SERVICE_NOTIFICATION); } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= DebugEnter() WHAT : called on api entry. prints a log entry resembling the following: CalledFunctionName(param1=value, etc.) ARGS : category - the debugging category for the logged function rt - lets us know what type the function returns function - the logged function's name format - user-supplied format string containing function args ... - optional parameter list RETURNS : nothing =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ void DebugEnter(int category, RETTYPE rt, LPCSTR function, const char* format, ...) { LPTHREADINFO pti = NULL; LPCALLINFO pci = NULL; if( !(g_dwDebugFlags & DBG_NO_DEBUG) ) { pti = GetThreadInfo(); pci = SetCallInfo(pti, category, rt, function); if( g_dwDebugFlags & category ) { char* buffer = new char[1024]; va_list arg_list; pti->depth++; if( buffer ) { // // if the user passed an arglist & some values, // we'll plug it in to the function entry listing // in the log. otherwise we just print empty parens // if( format ) { va_start(arg_list, format); wvsprintfA(buffer, format, arg_list); _debugout(pti, FALSE, FALSE, "%s(%s)", function, buffer); va_end(arg_list); } else { _debugout(pti, FALSE, FALSE, "%s()", function); } delete [] buffer; } } } } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= DebugLeave() WHAT : prints a log entry for the logged function displaying the return value. ARGS : retval - the value the logged function will return RETURNS : nothing. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ void DebugLeave(int retval) { LPTHREADINFO pti = NULL; LPCALLINFO pci = NULL; if( !(g_dwDebugFlags & DBG_NO_DEBUG) ) { pti = GetThreadInfo(); pci = GetCallInfo(pti); if( g_dwDebugFlags & pci->category ) { char* buffer = FormatCallReturnString(pci, retval); _debugout(pti, FALSE, FALSE, buffer); pti->depth--; delete [] buffer; } DeleteCallInfo(pci); } } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= DebugTrace() WHAT : prints a generic output line with the usual timestamp & thread id, etc. ARGS : format - user-supplied format string ... - optional parameter list RETURNS : nothing =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ void DebugTrace(const char* format, ...) { va_list arg_list; char buf[1024]; if( !(g_dwDebugFlags & DBG_NO_DEBUG) ) { va_start(arg_list, format); wvsprintfA(buf, format, arg_list); _debugout(GetThreadInfo(), FALSE, TRUE, buf); va_end(arg_list); } } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= DebugAssert() WHAT : logs asserts to the selected outputs but doesn't break execution. ARGS : condition - the stringized failure condition. file - the file containing the assert line - the line of code that asserted RETURNS : nothing =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ void DebugAssert(LPSTR condition, LPSTR file, int line) { LPTHREADINFO pti = GetThreadInfo(); LPCALLINFO pci = NULL; _debugout( pti, TRUE, FALSE, "\r\n\r\n\t*******************************************\r\n" \ "\t ASSERTION FAILED: \"%s\"\r\n" \ "\t %s (line %d)\r\n", condition, file, line ); for(pci = pti->stack; pci; pci = pci->next) { _debugout(pti, TRUE, FALSE, "\t %s", pci->fname); } _debugout(pti, TRUE, FALSE, "\r\n\t*******************************************\r\n"); } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= DebugDataDump*() WHAT : functions to dump a data buffer to the log file. ARGS : title - a legend for the dump data - the buffer len - number of interesting bytes in the buffer RETURNS : nothing =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ void DebugDataDump(LPSTR title, LPBYTE data, DWORD len) { DWORD n = 0L; DWORD offset = 0L; CHAR* buf = NULL; DebugTrace("%s (%#x bytes @ %#x)", title, len, data); buf = new CHAR[256]; while( len ) { n = DebugDataDumpFormat(buf, data, len); DebugTrace(buf); data += n; len -= n; } delete [] buf; } int DebugDataDumpFormat(LPSTR buffer, LPBYTE data, DWORD len) { // // note - plagiarized from similar code in wininet. // static char spaces[] = " "; DWORD n = 0L; DWORD bytes = 0L; DWORD offset = 0L; DWORD byte = 0L; CHAR ch; bytes = min(len, 16); offset = wsprintfA(buffer, "%08x ", data); for(n=0; n 127)) || ch == '%') ? '.' : ch; } buffer[offset + n] = '\0'; return bytes; } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= AcquireDebugFileLock() WHAT : synchronizes access to the log file handle. ARGS : none RETURNS : nothing =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ void AcquireDebugFileLock(void) { WaitForSingleObject(g_mtxDebugLogFile, INFINITE); } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ReleaseDebugFileLock() WHAT : releases a thread's lock on the log file handle ARGS : none RETURNS : nothing =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ void ReleaseDebugFileLock(void) { ReleaseMutex(g_mtxDebugLogFile); } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= GetThreadInfo() WHAT : extracts a THREADINFO struct from TLS. if one does not exist, this function allocates one and returns it. ARGS : none RETURNS : pointer to a THREADINFO struct. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ LPTHREADINFO GetThreadInfo(void) { LPTHREADINFO pti = (LPTHREADINFO) TlsGetValue(g_dwTlsIndex); if( !pti ) { pti = new THREADINFO; pti->threadid = GetCurrentThreadId(); pti->threadcat = 0; pti->depth = 0; pti->stack = NULL; TlsSetValue(g_dwTlsIndex, (LPVOID) pti); } return pti; } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= SetCallInfo() WHAT : allocates and pushes a CALLINFO struct onto the thread's internal call list. ARGS : pti - pointer to the thread's THREADINFO struct category - the debug category associated with the logged function rt - return type used by the logged function function - the function name RETURNS : pointer to a newly allocated CALLINFO struct =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ LPCALLINFO SetCallInfo(LPTHREADINFO pti, DWORD category, RETTYPE rt, LPCSTR function) { LPCALLINFO pci = NULL; LPCALLINFO plast = NULL; // // walk the call stack to the last item, // store the next-to-last position // for( pci = pti->stack; pci; pci = pci->next ) { plast = pci; } if( !pci ) { pci = new CALLINFO; // // if this is the first call on this thread, set the thread // category id. this makes logging more understandable by // remembering where a thread was first created and what it // was used for. the old method changed the caller id based // on the function category, which was dumb. // if( !pti->threadcat ) pti->threadcat = category; pci->category = category; pci->fname = function; pci->rettype = rt; pci->last = plast; pci->next = NULL; // // if this is the first element, insert it // at the head of the list, otherwise // link up with the last element // if( !pti->stack ) { pti->stack = pci; } else { plast->next = pci; } } return pci; } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= GetCallInfo() WHAT : retrieves the last THREADINFO struct from the threads call trace list. ARGS : pti - pointer to the THREADINFO struct whose call list you want RETURNS : pointer to a CALLINFO struct =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ LPCALLINFO GetCallInfo(LPTHREADINFO pti) { LPCALLINFO pci = NULL; if( pti->stack ) { for( pci = pti->stack; pci->next; pci = pci->next ); } return pci; } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= DeleteCallInfo() WHAT : pops the specified CALLINFO struct off the thread's call list and deletes it. if we just popped & deleted the last call record, then delete the thread's THREADINFO struct. ARGS : pci - the CALLINFO struct you wish to delete RETURNS : nothing =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ void DeleteCallInfo(LPCALLINFO pci) { LPTHREADINFO pti = GetThreadInfo(); // // if the call record we're dealing with isn't the top of the stack // then fix up the stack pointers // // if the current call record is the last then delete the THREADINFO // for this thread and NULL the TLS value // if( pci->last ) { pci->last->next = NULL; } else { delete pti; TlsSetValue(g_dwTlsIndex, NULL); } // // for all cases, free the call record // delete pci; } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= FormatCallReturnString() WHAT : examines the returning function's return type and formats a string containing the return value. in the case of known error codes, we include a string representation of the error (e.g. ERROR_SUCCESS). ARGS : pci - pointer to the CALLINFO struct for the returning function retval - the function's return value RETURNS : formatted character buffer =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ LPSTR FormatCallReturnString(LPCALLINFO pci, int retval) { char* buffer = new char[256]; int offset = 0; if( buffer ) { offset = wsprintfA( buffer, "%s() returned ", pci->fname ); switch( pci->rettype ) { case rt_void : { wsprintfA(buffer+offset, ""); } break; case rt_bool : { wsprintfA(buffer+offset, "%s", (retval ? "TRUE" : "FALSE")); } break; case rt_dword : { wsprintfA(buffer+offset, "%d [%s]", retval, MapErrorToString(retval)); } break; case rt_hresult : { wsprintfA(buffer+offset, "%x [%s]", retval, MapHResultToString(retval)); } break; case rt_string : { wsprintfA(buffer+offset, "%.16s", (LPSTR)retval); } break; default: { wsprintfA(buffer+offset, "?"); } } } return buffer; } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= MapCategoryToString() WHAT : maps a debug category to a string for the log file. ARGS : category - the category id RETURNS : string representation of the category id =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ LPSTR MapCategoryToString(int category) { switch(category) { case DBG_APP : return "app"; case DBG_WORKER : return "---"; default : return "???"; } } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= MapCompKeyToString() WHAT : maps a completion key to a string for the log file. ARGS : key - the completion key RETURNS : string representation of the completion key =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ LPSTR MapCompKeyToString(int key) { switch(key) { CASE_OF(CK_INVALID_KEY); CASE_OF(CK_NEW_CONNECTION); CASE_OF(CK_NORMAL); CASE_OF(CK_CANCEL_IO); CASE_OF(CK_TERMINATE_THREAD); default : { return "*** WARNING: Unrecognized completion key!! ***"; } } } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= _debugout() WHAT : the debug output workhorse. sloppy as jello in the Texas sun and i don't care. ARGS : pti - THREADINFO pointer fRaw - skip debug info formatting fTrace - flag that causes us to do in-function indenting format - printf format string ... - arglist RETURNS : nothing =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ void _debugout(LPTHREADINFO pti, BOOL fRaw, BOOL fTrace, const char* format, ...) { int offset = 0; char* buffer = new char[2048]; va_list arg_list; if( !buffer ) goto quit; // // check if the user wants verbose debug info // if( !fRaw ) { if( DBG_TIMESTAMP & g_dwDebugFlags ) { char* timestamp = _gettimestamp(); offset = wsprintfA(buffer, "%s ", timestamp); delete [] timestamp; } if( DBG_THREAD_INFO & g_dwDebugFlags ) { offset += wsprintfA(buffer+offset, "%0.8x:%0.3d ", pti->threadid, pti->depth); } if( DBG_CALL_INFO & g_dwDebugFlags ) { // // 260500 pmidge // changed this to use the thread category id instead of the caller's id. // offset += wsprintfA(buffer+offset, "<%s> ", MapCategoryToString(pti->threadcat)); } if( DBG_NEST_CALLS & g_dwDebugFlags ) { char* whitespace = _getwhitespace( (fTrace ? pti->depth+1 : pti->depth) ); offset += wsprintfA(buffer+offset, "%s", whitespace); delete [] whitespace; } } // // plug in caller's goo if present // if( format ) { va_start(arg_list, format); offset += wvsprintfA(buffer+offset, format, arg_list); wsprintfA(buffer+offset, "\r\n"); va_end(arg_list); } // // dump to selected outputs // // // BUGBUG: this app only runs on W2K, need to // investigate WMI support // if( DBG_TO_FILE & g_dwDebugFlags ) { DWORD dw = 0; AcquireDebugFileLock(); WriteFile( g_hDebugLogFile, buffer, strlen(buffer), &dw, NULL ); ReleaseDebugFileLock(); } if( DBG_TO_DEBUGGER & g_dwDebugFlags ) OutputDebugStringA(buffer); quit: delete [] buffer; } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= _gettimestamp( void ) WHAT : gets the current time, formats it, and returns it to the caller. the caller MUST free the return value when done. ARGS : none RETURNS : pointer to formatted time string =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ char* _gettimestamp( void ) { SYSTEMTIME st; char* buffer = new char[256]; if( buffer ) { GetLocalTime(&st); wsprintfA( buffer, "%0.2d:%0.2d:%0.2d.%0.3d", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds ); } return buffer; } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= _getwhitespace( int spaces ) WHAT : used to insert a number of spaces for indenting. caller must free return value. ARGS : spaces - number of spaces to insert RETURNS : pointer to character buffer filled with spaces =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ char* _getwhitespace(int spaces) { char* buffer = new char[(spaces * 2) + 1]; if( buffer ) { memset(buffer, ' ', (spaces * 2)); buffer[(spaces * 2)] = '\0'; } return buffer; } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= _opendebugfile( void ) WHAT : opens the debug log file. will stomp previous logs instead of appending. ARGS : none RETURNS : true or false based on whether the file was opened. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ BOOL _opendebugfile(void) { if( !g_hDebugLogFile ) { g_hDebugLogFile = CreateFile( DEBUG_DEFAULT_DBGFILE, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); } return (g_hDebugLogFile ? TRUE : FALSE); } /*++=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= _closedebugfile( void ) WHAT : closes the debug log file. ARGS : none RETURNS : nothing =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--*/ void _closedebugfile(void) { SAFECLOSE(g_hDebugLogFile); } #endif /* _DEBUG */