// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright (C) 1995 Microsoft Corporation. All Rights Reserved. // // MODULE: TapiInfo.c // // PURPOSE: Handles all Pretty Printing functions for the TapiComm sample. // // EXPORTED FUNCTIONS: These functions are for use by other modules. // // All of these pretty print to the debugging output. // OutputDebugLineCallback - Calls FormatLineCallback. // OutputDebugLineError - Calls OutputDebugLineErrorFileLine. // OutputDebugLastError - Calls OutputDebugLineErrorFileLine. // OutputDebugPrintf - Calls wsprintf // OutputDebugLineErrorFileLine - Calls FormatLineError // OutputDebugLastErrorFileLine - Calls FormatLastError // // All of these functions pretty print to a string buffer. // FormatLineError - Prints a LINEERR // FormatLastError - Prints a GetLastError error. // FormatLineCallback - Prints a lineCallbackFunc message. // // INTERNAL FUNCTION: These functions are for this module only. // strBinaryArrayAppend - prints a binary flag array to a buffer. #include #include #include "TapiInfo.h" // Maximum length of all internal string buffers. #define MAXOUTPUTSTRINGLENGTH 4096 // define to make accessing arrays easy. #define sizeofArray(pArray) (sizeof(pArray) / sizeof((pArray)[0])) //***************************************** // Internal prototypes. //***************************************** static long strBinaryArrayAppend(LPSTR pszOutputBuffer, DWORD dwFlags, LPSTR szStringArray[], DWORD dwSizeofStringArray); //***************************************** // Global arrays for interpreting TAPI constants. //***************************************** LPSTR pszLineErrorNameArray[] = { "", "LINEERR_ALLOCATED", "LINEERR_BADDEVICEID", "LINEERR_BEARERMODEUNAVAIL", "LINEERR Unused constant, ERROR!!", "LINEERR_CALLUNAVAIL", "LINEERR_COMPLETIONOVERRUN", "LINEERR_CONFERENCEFULL", "LINEERR_DIALBILLING", "LINEERR_DIALDIALTONE", "LINEERR_DIALPROMPT", "LINEERR_DIALQUIET", "LINEERR_INCOMPATIBLEAPIVERSION", "LINEERR_INCOMPATIBLEEXTVERSION", "LINEERR_INIFILECORRUPT", "LINEERR_INUSE", "LINEERR_INVALADDRESS", "LINEERR_INVALADDRESSID", "LINEERR_INVALADDRESSMODE", "LINEERR_INVALADDRESSSTATE", "LINEERR_INVALAPPHANDLE", "LINEERR_INVALAPPNAME", "LINEERR_INVALBEARERMODE", "LINEERR_INVALCALLCOMPLMODE", "LINEERR_INVALCALLHANDLE", "LINEERR_INVALCALLPARAMS", "LINEERR_INVALCALLPRIVILEGE", "LINEERR_INVALCALLSELECT", "LINEERR_INVALCALLSTATE", "LINEERR_INVALCALLSTATELIST", "LINEERR_INVALCARD", "LINEERR_INVALCOMPLETIONID", "LINEERR_INVALCONFCALLHANDLE", "LINEERR_INVALCONSULTCALLHANDLE", "LINEERR_INVALCOUNTRYCODE", "LINEERR_INVALDEVICECLASS", "LINEERR_INVALDEVICEHANDLE", "LINEERR_INVALDIALPARAMS", "LINEERR_INVALDIGITLIST", "LINEERR_INVALDIGITMODE", "LINEERR_INVALDIGITS", "LINEERR_INVALEXTVERSION", "LINEERR_INVALGROUPID", "LINEERR_INVALLINEHANDLE", "LINEERR_INVALLINESTATE", "LINEERR_INVALLOCATION", "LINEERR_INVALMEDIALIST", "LINEERR_INVALMEDIAMODE", "LINEERR_INVALMESSAGEID", "LINEERR Unused constant, ERROR!!", "LINEERR_INVALPARAM", "LINEERR_INVALPARKID", "LINEERR_INVALPARKMODE", "LINEERR_INVALPOINTER", "LINEERR_INVALPRIVSELECT", "LINEERR_INVALRATE", "LINEERR_INVALREQUESTMODE", "LINEERR_INVALTERMINALID", "LINEERR_INVALTERMINALMODE", "LINEERR_INVALTIMEOUT", "LINEERR_INVALTONE", "LINEERR_INVALTONELIST", "LINEERR_INVALTONEMODE", "LINEERR_INVALTRANSFERMODE", "LINEERR_LINEMAPPERFAILED", "LINEERR_NOCONFERENCE", "LINEERR_NODEVICE", "LINEERR_NODRIVER", "LINEERR_NOMEM", "LINEERR_NOREQUEST", "LINEERR_NOTOWNER", "LINEERR_NOTREGISTERED", "LINEERR_OPERATIONFAILED", "LINEERR_OPERATIONUNAVAIL", "LINEERR_RATEUNAVAIL", "LINEERR_RESOURCEUNAVAIL", "LINEERR_REQUESTOVERRUN", "LINEERR_STRUCTURETOOSMALL", "LINEERR_TARGETNOTFOUND", "LINEERR_TARGETSELF", "LINEERR_UNINITIALIZED", "LINEERR_USERUSERINFOTOOBIG", "LINEERR_REINIT", "LINEERR_ADDRESSBLOCKED", "LINEERR_BILLINGREJECTED", "LINEERR_INVALFEATURE", "LINEERR_NOMULTIPLEINSTANCE" }; LPSTR psz_dwMsg[] = { "LINE_ADDRESSSTATE", "LINE_CALLINFO", "LINE_CALLSTATE", "LINE_CLOSE", "LINE_DEVSPECIFIC", "LINE_DEVSPECIFICFEATURE", "LINE_GATHERDIGITS", "LINE_GENERATE", "LINE_LINEDEVSTATE", "LINE_MONITORDIGITS", "LINE_MONITORMEDIA", "LINE_MONITORTONE", "LINE_REPLY", "LINE_REQUEST", "PHONE_BUTTON", "PHONE_CLOSE", "PHONE_DEVSPECIFIC", "PHONE_REPLY", "PHONE_STATE", "LINE_CREATE", "PHONE_CREATE" }; LPSTR pszfLINEADDRESSSTATE[] = { "Unknown LINEADDRESSSTATE information", "LINEADDRESSSTATE_OTHER", "LINEADDRESSSTATE_DEVSPECIFIC", "LINEADDRESSSTATE_INUSEZERO", "LINEADDRESSSTATE_INUSEONE", "LINEADDRESSSTATE_INUSEMANY", "LINEADDRESSSTATE_NUMCALLS", "LINEADDRESSSTATE_FORWARD", "LINEADDRESSSTATE_TERMINALS", "LINEADDRESSSTATE_CAPSCHANGE" }; LPSTR pszfLINECALLINFOSTATE[] = { "Unknown LINECALLINFOSTATE state", "LINECALLINFOSTATE_OTHER", "LINECALLINFOSTATE_DEVSPECIFIC", "LINECALLINFOSTATE_BEARERMODE", "LINECALLINFOSTATE_RATE", "LINECALLINFOSTATE_MEDIAMODE", "LINECALLINFOSTATE_APPSPECIFIC", "LINECALLINFOSTATE_CALLID", "LINECALLINFOSTATE_RELATEDCALLID", "LINECALLINFOSTATE_ORIGIN", "LINECALLINFOSTATE_REASON", "LINECALLINFOSTATE_COMPLETIONID", "LINECALLINFOSTATE_NUMOWNERINCR", "LINECALLINFOSTATE_NUMOWNERDECR", "LINECALLINFOSTATE_NUMMONITORS", "LINECALLINFOSTATE_TRUNK", "LINECALLINFOSTATE_CALLERID", "LINECALLINFOSTATE_CALLEDID", "LINECALLINFOSTATE_CONNECTEDID", "LINECALLINFOSTATE_REDIRECTIONID", "LINECALLINFOSTATE_REDIRECTINGID", "LINECALLINFOSTATE_DISPLAY", "LINECALLINFOSTATE_USERUSERINFO", "LINECALLINFOSTATE_HIGHLEVELCOMP", "LINECALLINFOSTATE_LOWLEVELCOMP", "LINECALLINFOSTATE_CHARGINGINFO", "LINECALLINFOSTATE_TERMINAL", "LINECALLINFOSTATE_DIALPARAMS", "LINECALLINFOSTATE_MONITORMODES" }; LPSTR pszfLINECALLSTATE[] = { "Unknown LINECALLSTATE state", "LINECALLSTATE_IDLE", "LINECALLSTATE_OFFERING", "LINECALLSTATE_ACCEPTED", "LINECALLSTATE_DIALTONE", "LINECALLSTATE_DIALING", "LINECALLSTATE_RINGBACK", "LINECALLSTATE_BUSY", "LINECALLSTATE_SPECIALINFO", "LINECALLSTATE_CONNECTED", "LINECALLSTATE_PROCEEDING", "LINECALLSTATE_ONHOLD", "LINECALLSTATE_CONFERENCED", "LINECALLSTATE_ONHOLDPENDCONF", "LINECALLSTATE_ONHOLDPENDTRANSFER", "LINECALLSTATE_DISCONNECTED", "LINECALLSTATE_UNKNOWN" }; LPSTR pszfLINEDIALTONEMODE[] = { "Unknown LINEDIALTONE information", "LINEDIALTONEMODE_NORMAL", "LINEDIALTONEMODE_SPECIAL", "LINEDIALTONEMODE_INTERNAL", "LINEDIALTONEMODE_EXTERNAL", "LINEDIALTONEMODE_UNKNOWN", "LINEDIALTONEMODE_UNAVAIL" }; LPSTR pszfLINEBUSYMODE[] = { "Unknown LINEBUSYMODE information", "LINEBUSYMODE_STATION", "LINEBUSYMODE_TRUNK", "LINEBUSYMODE_UNKNOWN", "LINEBUSYMODE_UNAVAIL" }; LPSTR pszfLINESPECIALINFO[] = { "Unknown LINESPECIALINFO information", "LINESPECIALINFO_NOCIRCUIT", "LINESPECIALINFO_CUSTIRREG", "LINESPECIALINFO_REORDER", "LINESPECIALINFO_UNKNOWN", "LINESPECIALINFO_UNAVAIL" }; LPSTR pszfLINEDISCONNECTED[] = { "Unknown LINEDISCONNECTED information", "LINEDISCONNECTMODE_NORMAL", "LINEDISCONNECTMODE_UNKNOWN", "LINEDISCONNECTMODE_REJECT", "LINEDISCONNECTMODE_PICKUP", "LINEDISCONNECTMODE_FORWARDED", "LINEDISCONNECTMODE_BUSY", "LINEDISCONNECTMODE_NOANSWER", "LINEDISCONNECTMODE_BADADDRESS", "LINEDISCONNECTMODE_UNREACHABLE", "LINEDISCONNECTMODE_CONGESTION", "LINEDISCONNECTMODE_INCOMPATIBLE", "LINEDISCONNECTMODE_UNAVAIL", "LINEDISCONNECTMODE_NODIALTONE" }; LPSTR pszfLINECALLPRIVILEGE[] = { "", "LINECALLPRIVILEGE_NONE", "LINECALLPRIVILEGE_MONITOR", "LINECALLPRIVILEGE_OWNER" }; LPSTR pszfLINEGATHERTERM[] = { "Unknown LINEGATHERTERM message", "LINEGATHERTERM_BUFFERFULL", "LINEGATHERTERM_TERMDIGIT", "LINEGATHERTERM_FIRSTTIMEOUT", "LINEGATHERTERM_INTERTIMEOUT", "LINEGATHERTERM_CANCEL" }; LPSTR pszfLINEGENERATETERM[] = { "Unknown LINEGENERATETERM message", "LINEGENERATETERM_DONE", "LINEGENERATETERM_CANCEL" }; LPSTR pszfLINEDEVSTATE[] = { "Unknown LINEDEVESTATE state", "LINEDEVSTATE_OTHER", "LINEDEVSTATE_RINGING", "LINEDEVSTATE_CONNECTED", "LINEDEVSTATE_DISCONNECTED", "LINEDEVSTATE_MSGWAITON", "LINEDEVSTATE_MSGWAITOFF", "LINEDEVSTATE_INSERVICE", "LINEDEVSTATE_OUTOFSERVICE", "LINEDEVSTATE_MAINTENANCE", "LINEDEVSTATE_OPEN", "LINEDEVSTATE_CLOSE", "LINEDEVSTATE_NUMCALLS", "LINEDEVSTATE_NUMCOMPLETIONS", "LINEDEVSTATE_TERMINALS", "LINEDEVSTATE_ROAMMODE", "LINEDEVSTATE_BATTERY", "LINEDEVSTATE_SIGNAL", "LINEDEVSTATE_DEVSPECIFIC", "LINEDEVSTATE_REINIT", "LINEDEVSTATE_LOCK", "LINEDEVSTATE_CAPSCHANGE", "LINEDEVSTATE_CONFIGCHANGE", "LINEDEVSTATE_TRANSLATECHANGE", "LINEDEVSTATE_COMPLCANCEL", "LINEDEVSTATE_REMOVED" }; LPSTR pszfLINEDIGITMODE[] = { "Unknown LINEDIGITMODE mode", "LINEDIGITMODE_PULSE", "LINEDIGITMODE_DTMF", "LINEDIGITMODE_DTMFEND" }; LPSTR pszfLINEMEDIAMODE[] = { "Unknown LINEMEDIAMODE mode", "UnUsed LINEMEDIAMODE mode, ERROR!!", "LINEMEDIAMODE_UNKNOWN", "LINEMEDIAMODE_INTERACTIVEVOICE", "LINEMEDIAMODE_AUTOMATEDVOICE", "LINEMEDIAMODE_DATAMODEM", "LINEMEDIAMODE_G3FAX", "LINEMEDIAMODE_TDD", "LINEMEDIAMODE_G4FAX", "LINEMEDIAMODE_DIGITALDATA", "LINEMEDIAMODE_TELETEX", "LINEMEDIAMODE_VIDEOTEX", "LINEMEDIAMODE_TELEX", "LINEMEDIAMODE_MIXED", "LINEMEDIAMODE_ADSI", "LINEMEDIAMODE_VOICEVIEW" }; LPSTR pszfLINEREQUESTMODE[] = { "Unknown LINEREQUESTMODE message", "LINEREQUESTMODE_MAKECALL", "LINEREQUESTMODE_MEDIACALL", "LINEREQUESTMODE_DROP" }; // // MACRO: OutputDebugLineError(long, LPSTR) // // PURPOSE: Pretty print a line error to the debugging output. // // PARAMETERS: // lLineError - Actual error code to decipher. // pszPrefix - String to prepend to the printed message. // // RETURN VALUE: // none // // COMMENTS: // This macro is actually defined in the .h file. // It will take a LINEERR error, turn it into a human // readable string, prepend pszPrefix (so you // can tag your errors), append __FILE__ and __LINE__ // and print it to the debugging output. // This macro is just a wrapper around OutputDebugLineErrorFileLine // that is necessary to get proper values for __FILE__ and __LINE__. // // /* #define OuputDebugLineError(lLineError, pszPrefix) \ OutputDebugLineErrorFileLine(lLineError, pszPrefix,\ __FILE__, __LINE__) */ // // FUNCTION: OutputDebugLineErrorFileLine(..) // // PURPOSE: Pretty print a line error to the debugging output. // // PARAMETERS: // lLineError - Actual error code to decipher. // pszPrefix - String to prepend to the printed message. // szFileName - Filename the error occured in. // nLineNumber - Line number the error occured at. // // RETURN VALUE: // none // // COMMENTS: // This is the actual function that OutputDebugLineError // expands to. Its not likely to be usefull except // through the OutputDebugLineError macro, or to print // errors without line and file information. // // If szFileName == NULL, then the File and Line are not printed. // // Note that there is an internal string length limit of // MAXOUTPUTSTRINGLENGTH. If this length is exceeded, // the behavior will be the same as wsprintf, although // it will be undetectable. *KEEP szPrefix SHORT!* // // void OutputDebugLineErrorFileLine( long lLineError, LPSTR szPrefix, LPSTR szFileName, DWORD nLineNumber) { LPSTR szLineError; char szOutputLineError[MAXOUTPUTSTRINGLENGTH]; if (szPrefix == NULL) szPrefix = ""; // Pretty print the error message. szLineError = FormatLineError(lLineError, NULL, 0); // The only reason FormatLineError should fail is "Out of memory". if (szLineError == NULL) { if (szFileName == NULL) wsprintf(szOutputLineError, "%sOut of memory", szPrefix); else wsprintf(szOutputLineError, "%sOut of memory in file %s, line %d\r\n", szPrefix, szFileName, nLineNumber); OutputDebugString(szOutputLineError); return; } // If szFileName, then use it; else don't. if (szFileName != NULL) { wsprintf(szOutputLineError, "%s\r\n\tTapi Line Error: \"%s\" \r\n\tin File \"%s\", Line %d\r\n", szPrefix, szLineError, szFileName, nLineNumber); } else { wsprintf(szOutputLineError, "%s\r\n\tTapi Line Error: \"%s\"\r\n", szPrefix, szLineError); } // Pointer returned from FormatLineError *must* be freed! LocalFree(szLineError); // Print it! OutputDebugString(szOutputLineError); return; } // // FUNCTION: FormatLineError(long, LPSTR, DWORD) // // PURPOSE: Pretty print a line error to a string. // // PARAMETERS: // lLineError - Actual error code to decipher. // szOutputBuffer - String buffer to pretty print to. // dwSizeofOutputBuffer - Size of String buffer. // // RETURN VALUE: // Returns the buffer printed to. // // COMMENTS: // If szOutputBuffer isn't big enough to hold the whole string, // then the string gets truncated to fit the buffer. // // If szOutputBuffer == NULL, then dwSizeofOutputBuffer // is ignored, a buffer 'big enough' is LocalAlloc()d and // a pointer to it is returned. However, its *very* important // that this pointer be LocalFree()d by the calling application. // // LPSTR FormatLineError(long lLineError, LPSTR szOutputBuffer, DWORD dwSizeofOutputBuffer) { char szUnknownLineError[256]; LPSTR szLineError; int nSizeofLineError; long lErrorIndex; DWORD * pdwLineError; // Strip off the high bit to make the error code positive. pdwLineError = (LPDWORD) &lLineError; lErrorIndex = (long) (0x7FFFFFFF & *pdwLineError); // Is it an unknown error? if ((lErrorIndex >= sizeofArray(pszLineErrorNameArray)) || (lErrorIndex < 0)) { nSizeofLineError = wsprintf(szUnknownLineError, "Unknown TAPI line error code: 0x%lx", lLineError); szLineError = szUnknownLineError; } else { szLineError = pszLineErrorNameArray[lErrorIndex]; nSizeofLineError = strlen(szLineError); } // allocate a buffer if necessary if (szOutputBuffer == NULL) { szOutputBuffer = (LPSTR) LocalAlloc(LPTR, nSizeofLineError + 1); if (szOutputBuffer == NULL) return NULL; } else // truncate string if it won't fit in the specified buffer. { if ((DWORD) nSizeofLineError >= dwSizeofOutputBuffer) nSizeofLineError = dwSizeofOutputBuffer - 1; } // Put the string into the buffer and null terminate. memcpy(szOutputBuffer, szLineError, nSizeofLineError); szOutputBuffer[nSizeofLineError] = '\0'; return szOutputBuffer; } // // MACRO: OutputDebugLastError(DWORD, LPSTR) // // PURPOSE: Pretty print a system error to the debugging output. // // PARAMETERS: // dwLastError - Actual error code to decipher. // pszPrefix - String to prepend to the printed message. // // RETURN VALUE: // none // // COMMENTS: // This macro is actually defined in the .h file. // It will take an error that was retrieved by GetLastError(), // turn it into a human readable string, prepend pszPrefix // (so you can tag your errors), append __FILE__ and __LINE__ // and print it to the debugging output. // // This macro is just a wrapper around OutputDebugLastErrorFileLine // that is necessary to get proper values for __FILE__ and __LINE__. // // /* #define OuputDebugLastError(dwLastError, pszPrefix) \ OutputDebugLastErrorFileLine(dwLastError, pszPrefix,\ __FILE__, __LINE__) */ // // FUNCTION: OutputDebugLastErrorFileLine(..) // // PURPOSE: Pretty print a line error to the debugging output. // // PARAMETERS: // dwLastError - Actual error code to decipher. // pszPrefix - String to prepend to the printed message. // szFileName - Filename the error occured in. // nLineNumber - Line number the error occured at. // // RETURN VALUE: // none // // COMMENTS: // This is the actual function that OutputDebugLastError // expands to. Its not likely to be usefull except // through the OutputDebugLastError macro or to print // errors without line and file information. // // If szFileName == NULL, then the File and Line are not printed. // // Note that there is an internal string length limit of // MAXOUTPUTSTRINGLENGTH. If this length is exceeded, // the behavior will be the same as wsprintf, although // it will be undetectable. *KEEP szPrefix SHORT!* // // void OutputDebugLastErrorFileLine( DWORD dwLastError, LPSTR szPrefix, LPSTR szFileName, DWORD nLineNumber) { LPSTR szLastError; char szOutputLastError[MAXOUTPUTSTRINGLENGTH]; if (szPrefix == NULL) szPrefix = ""; // Pretty print the error. szLastError = FormatLastError(dwLastError, NULL, 0); // The only reason FormatLastError should fail is "Out of memory". if (szLastError == NULL) { if (szFileName == NULL) wsprintf(szOutputLastError, "%sOut of memory\r\n", szPrefix); else wsprintf(szOutputLastError, "%sOut of memory in file %s, line %d\r\n", szPrefix, szFileName, nLineNumber); OutputDebugString(szOutputLastError); return; } // If szFileName, then use it; else don't. if (szFileName != NULL) { wsprintf(szOutputLastError, "%sGetLastError returned: \"%s\" in File \"%s\", Line %d\r\n", szPrefix, szLastError, szFileName, nLineNumber); } else { wsprintf(szOutputLastError, "%sGetLastError returned: \"%s\"\r\n", szPrefix, szLastError); } // Pointer returned from FormatLineError *must* be freed! LocalFree(szLastError); // Print it! OutputDebugString(szOutputLastError); return; } // // FUNCTION: FormatLastError(DWORD, LPSTR, DWORD) // // PURPOSE: Pretty print a system error to a string. // // PARAMETERS: // dwLastError - Actual error code to decipher. // szOutputBuffer - String buffer to pretty print to. // dwSizeofOutputBuffer - Size of String buffer. // // RETURN VALUE: // Returns the buffer printed to. // // COMMENTS: // If szOutputBuffer isn't big enough to hold the whole string, // then the string gets truncated to fit the buffer. // // If szOutputBuffer == NULL, then dwSizeofOutputBuffer // is ignored, a buffer 'big enough' is LocalAlloc()d and // a pointer to it is returned. However, its *very* important // that this pointer be LocalFree()d by the calling application. // // LPSTR FormatLastError(DWORD dwLastError, LPSTR szOutputBuffer, DWORD dwSizeofOutputBuffer) { DWORD dwRetFM; DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM; // Should we allocate a buffer? if (szOutputBuffer == NULL) { // Actually, we make FormatMessage allocate the buffer, if needed. dwFlags |= FORMAT_MESSAGE_ALLOCATE_BUFFER; // minimum size FormatMessage should allocate. dwSizeofOutputBuffer = 1; } // Make FormatMessage pretty print the system error. dwRetFM = FormatMessage( dwFlags, NULL, dwLastError, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (LPTSTR) &szOutputBuffer, dwSizeofOutputBuffer, NULL); // FormatMessage failed to print the error. if (dwRetFM == 0) { DWORD dwGetLastError; LPSTR szFormatMessageError; dwGetLastError = GetLastError(); // If we asked FormatMessage to allocate a buffer, then it // might have allocated one. Lets be safe and LocalFree it. if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) { __try { LocalFree(szOutputBuffer); } __except(EXCEPTION_EXECUTE_HANDLER) { // Actually, we do nothing for this fault. If // there was a fault, it meant the buffer wasn't // allocated, and the LocalFree was unnecessary. ; } szOutputBuffer = (char *) LocalAlloc(LPTR, MAXOUTPUTSTRINGLENGTH); dwSizeofOutputBuffer = MAXOUTPUTSTRINGLENGTH; if (szOutputBuffer == NULL) { OutputDebugString("Out of memory trying to FormatLastError\r\n"); return NULL; } } szFormatMessageError = FormatLastError(dwGetLastError, NULL, 0); if (szFormatMessageError == NULL) return NULL; wsprintf(szOutputBuffer, "FormatMessage failed on error 0x%lx for the following reason: %s", dwLastError, szFormatMessageError); LocalFree(szFormatMessageError); } return szOutputBuffer; } // // FUNCTION: OutputDebugLineCallback(...) // // PURPOSE: Pretty print a message passed into a lineCallbackFunc. // // PARAMETERS: // Standard lineCallbackFunc parameters. // // RETURN VALUE: // none. // // COMMENTS: // // This function takes all of the parameters passed into a // lineCallbackFunc callback function, and pretty prints the // meaning of the message. It then prints the result to // the debugging output. // // void OutputDebugLineCallback( DWORD dwDevice, DWORD dwMsg, DWORD dwCallbackInstance, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3) { char szOutputBuff[MAXOUTPUTSTRINGLENGTH]; FormatLineCallback(szOutputBuff, dwDevice, dwMsg, dwCallbackInstance, dwParam1, dwParam2, dwParam3); strcat(szOutputBuff,"\r\n"); OutputDebugString(szOutputBuff); } // // FUNCTION: FormatLineCallback(...) // // PURPOSE: Pretty prints into a buffer a lineCallbackFunc message. // // PARAMETERS: // Standard lineCallbackFunc parameters. // // RETURN VALUE: // The pointer to the buffer that has the resulting string. // // COMMENTS: // // This function takes all of the parameters passed into a // lineCallbackFunc callback function, and pretty prints the // meaning of the message. It then returns the pointer to // the buffer containing this string. // // If szOutputBuffer == NULL, then a buffer is LocalAlloc()d // and returned. However, it is *very* important that this buffer // is LocalFree()d. // LPSTR FormatLineCallback(LPSTR szOutputBuffer, DWORD dwDevice, DWORD dwMsg, DWORD dwCallbackInstance, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3) { long lBufferIndex = 0; // Allocate the buffer if necessary. if (szOutputBuffer == NULL) { szOutputBuffer = (LPSTR) LocalAlloc(LPTR, MAXOUTPUTSTRINGLENGTH); if (szOutputBuffer == NULL) return NULL; } // Is this a known message? if (dwMsg >= sizeofArray(psz_dwMsg)) { wsprintf(szOutputBuffer, "Tapi Msg: Unknown dwMsg: '0x%lx', " "dwDevice: '0x%lx', dwInst: '0x%lx', " "dwP1: '0x%lx', dwP2: '0x%lx', dwP3: '0x%lx'", dwMsg, dwDevice, dwCallbackInstance, dwParam1, dwParam2, dwParam3); return szOutputBuffer; } // Lets start pretty printing. lBufferIndex += wsprintf(szOutputBuffer, "Tapi Msg(%s) On(0x%lx)\r\n\t ", psz_dwMsg[dwMsg], dwDevice); // Which message was it? And start decoding it! // How the message is decoded depends entirely on the message. // READ THE HELP FILES if you more information on this. switch(dwMsg) { case LINE_ADDRESSSTATE: { lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), "Address ID: 0x%lx, Address State: ", dwParam1); lBufferIndex += strBinaryArrayAppend(&(szOutputBuffer[lBufferIndex]), dwParam2, pszfLINEADDRESSSTATE, sizeofArray(pszfLINEADDRESSSTATE)); break; } case LINE_CALLINFO: { lBufferIndex += strBinaryArrayAppend(&(szOutputBuffer[lBufferIndex]), dwParam1, pszfLINECALLINFOSTATE, sizeofArray(pszfLINECALLINFOSTATE)); break; } case LINE_CALLSTATE: { lBufferIndex += strBinaryArrayAppend(&(szOutputBuffer[lBufferIndex]), dwParam3, pszfLINECALLPRIVILEGE, sizeofArray(pszfLINECALLPRIVILEGE)); lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), "; "); lBufferIndex += strBinaryArrayAppend(&(szOutputBuffer[lBufferIndex]), dwParam1, pszfLINECALLSTATE, sizeofArray(pszfLINECALLSTATE)); switch(dwParam1) { case LINECALLSTATE_DIALTONE: { lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), ": "); lBufferIndex += strBinaryArrayAppend(&(szOutputBuffer[lBufferIndex]), dwParam2, pszfLINEDIALTONEMODE, sizeofArray(pszfLINEDIALTONEMODE)); break; } case LINECALLSTATE_BUSY: { lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), ": "); lBufferIndex += strBinaryArrayAppend(&(szOutputBuffer[lBufferIndex]), dwParam2, pszfLINEBUSYMODE, sizeofArray(pszfLINEBUSYMODE)); break; } case LINECALLSTATE_SPECIALINFO: { lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), ": "); lBufferIndex += strBinaryArrayAppend(&(szOutputBuffer[lBufferIndex]), dwParam2, pszfLINESPECIALINFO, sizeofArray(pszfLINESPECIALINFO)); break; } case LINECALLSTATE_DISCONNECTED: { lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), ": "); lBufferIndex += strBinaryArrayAppend(&(szOutputBuffer[lBufferIndex]), dwParam2, pszfLINEDISCONNECTED, sizeofArray(pszfLINEDISCONNECTED)); break; } case LINECALLSTATE_CONFERENCED: { lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), ": Parent conference call handle: 0x%lx", dwParam2); break; } } break; } case LINE_CLOSE: break; case LINE_DEVSPECIFIC: break; case LINE_DEVSPECIFICFEATURE: break; case LINE_GATHERDIGITS: { lBufferIndex += strBinaryArrayAppend(&(szOutputBuffer[lBufferIndex]), dwParam1, pszfLINEGATHERTERM, sizeofArray(pszfLINEGATHERTERM)); break; } case LINE_GENERATE: { lBufferIndex += strBinaryArrayAppend(&(szOutputBuffer[lBufferIndex]), dwParam1, pszfLINEGENERATETERM, sizeofArray(pszfLINEGENERATETERM)); break; } case LINE_LINEDEVSTATE: { lBufferIndex += strBinaryArrayAppend(&(szOutputBuffer[lBufferIndex]), dwParam1, pszfLINEDEVSTATE, sizeofArray(pszfLINEDEVSTATE)); switch(dwParam1) { case LINEDEVSTATE_RINGING: lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), "; Ring Mode: 0x%lx, Ring Count: %lu" ,dwParam2, dwParam3); break; case LINEDEVSTATE_REINIT: { switch(dwParam2) { case LINE_CREATE: lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), "; ReInit reason: LINE_CREATE, " "New Line Device ID '0x%lx'" , dwParam3); break; case LINE_LINEDEVSTATE: lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), "; ReInit reason: LINE_LINEDEVSTATE, "); lBufferIndex += strBinaryArrayAppend(&(szOutputBuffer[lBufferIndex]), dwParam3, pszfLINEDEVSTATE, sizeofArray(pszfLINEDEVSTATE)); break; case 0: break; default: lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), "; ReInit reason: %s, dwParam3: 0x%lx" ,psz_dwMsg[dwParam2], dwParam3); break; } break; } default: break; } break; } case LINE_MONITORDIGITS: { lBufferIndex += strBinaryArrayAppend(&(szOutputBuffer[lBufferIndex]), dwParam2, pszfLINEDIGITMODE, sizeofArray(pszfLINEDIGITMODE)); lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), ", Received: '%c'", LOBYTE(LOWORD(dwParam1))); break; } case LINE_MONITORMEDIA: { lBufferIndex += strBinaryArrayAppend(&(szOutputBuffer[lBufferIndex]), dwParam1, pszfLINEMEDIAMODE, sizeofArray(pszfLINEMEDIAMODE)); break; } case LINE_MONITORTONE: { lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), "AppSpecific tone '%lu'", dwParam1); break; } case LINE_REPLY: { if (dwParam2 == 0) { lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), "Request ID: 0x%lx; Successful reply!", dwParam1); } else { char szTmpBuff[256]; FormatLineError((long) dwParam2, szTmpBuff, 255); lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), "Request ID: 0x%lx; UnSuccessful reply; %s", dwParam1, szTmpBuff); } break; } case LINE_REQUEST: { lBufferIndex += strBinaryArrayAppend(&(szOutputBuffer[lBufferIndex]), dwParam1, pszfLINEREQUESTMODE, sizeofArray(pszfLINEREQUESTMODE)); switch(dwParam1) { case LINEREQUESTMODE_DROP: { char szHwndName[1024]; SendMessage((HWND) dwParam2, WM_GETTEXT, 1024, (long) szHwndName); lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), ": hwnd dropping = 0x%lx, \"%s\"; wRequestID = %u", dwParam2, szHwndName, LOWORD(dwParam3)); break; } default: break; } break; } case LINE_CREATE: { lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), "New Line Device ID '0x%lx'", dwParam1); break; } case PHONE_CREATE: { lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), "New Phone Device ID '0x%lx'", dwParam1); break; } default: lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), "dwParam1: 0x%lx , dwParam2: 0x%lx , dwParam3: 0x%lx", dwParam1, dwParam2, dwParam3); break; } // End switch(dwMsg) // return that pointer! return szOutputBuffer; } // // FUNCTION: strBinaryArrayAppend(LPSTR, DWORD, LPSTR *, DWORD) // // PURPOSE: Takes a bitmapped DWORD, an array representing that // binary mapping, and pretty prints it to a buffer. // // PARAMETERS: // szOutputBuffer - Buffer to print to. // dwFlags - Binary mapped flags to interpret. // szStringArray - Array of strings. // dwSizeofStringArray - number of elements in szStringArray. // // RETURN VALUE: // The number of characters printed into szOutputBuffer. // // COMMENTS: // // This function takes dwFlags and checks each bit. If the // bit is set, the appropriate string (taken from szStringArray) // is printed to the szOutputBuffer string buffer. If there were // more bits set in the string than elements in the array, and error // is also tagged on the end. // // This function is intended to be used only within the TapiInfo module. // static long strBinaryArrayAppend(LPSTR szOutputBuffer, DWORD dwFlags, LPSTR szStringArray[], DWORD dwSizeofStringArray) { DWORD dwIndex = 1, dwPower = 1; long lBufferIndex = 0; BOOL bFirst = TRUE; // The zeroth element in every bitmapped array is the "unknown" or // "unchanged" message. if (dwFlags == 0) { lBufferIndex = wsprintf(szOutputBuffer, "%s", szStringArray[0]); return lBufferIndex; } // iterate through the flags and check each one. while(dwIndex < dwSizeofStringArray) { // If we find one, print it. if (dwFlags & dwPower) // Seporate each printing with a ", " except the first one. if (bFirst) { lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), "%s", szStringArray[dwIndex]); bFirst = FALSE; } else lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), ", %s", szStringArray[dwIndex]); dwIndex ++; dwFlags &= ~dwPower; // clear it so we know we checked it. dwPower *= 2; } // If there are any flags left, they were not in the array. if (dwFlags) { if (bFirst) lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), "Unknown flags '0x%lx'", dwFlags); else lBufferIndex += wsprintf(&(szOutputBuffer[lBufferIndex]), ", Unknown flags '0x%lx'", dwFlags); } // how many did we print into the buffer? return lBufferIndex; } // // FUNCTION: OutputDebugPrintf(LPCSTR, ...) // // PURPOSE: wsprintf to the debugging output. // // PARAMETERS: // Exactly the same as wsprintf. // // RETURN VALUE: // none. // // COMMENTS: // // This function takes exactly the same parameters as wsprintf and // prints the results to the debugging output. // void __cdecl OutputDebugPrintf(LPCSTR lpszFormat, ...) { char szOutput[MAXOUTPUTSTRINGLENGTH]; va_list v1; DWORD dwSize; va_start(v1, lpszFormat); dwSize = wvsprintf(szOutput, lpszFormat, v1); if (szOutput[dwSize-1] != '\n') strcat(szOutput, "\r\n"); OutputDebugString(szOutput); }