//============================================================================ // Copyright (c) 1995, Microsoft Corporation // // File: api.c // // History: // Abolade Gbadegesin July-25-1995 Created // // API entry-points for tracing dll //============================================================================ #include #include #include #include #include #include #include "trace.h" #define ENTER_TRACE_API(lpserver) \ (((lpserver)!=NULL) && ((lpserver)->TS_StopEvent != NULL)) // // called before any other functions; responsible for creating // and initializing a client structure for the caller // and notifying the server of the new client // DWORD APIENTRY TraceRegisterEx( IN LPCTSTR lpszCallerName, IN DWORD dwFlags ) { DWORD dwErr, dwClientID; LPTRACE_SERVER lpserver; LPTRACE_CLIENT lpclient, *lplpc, *lplpcstart, *lplpcend; lpserver = GET_TRACE_SERVER(); ASSERTMSG ("Could not create trace server ", lpserver!=NULL); if (!lpserver) return INVALID_TRACEID; TRACE_ACQUIRE_WRITELOCK(lpserver); // // complete the console thread event creations if not done before // if (lpserver->TS_TableEvent == NULL) { dwErr = TraceCreateServerComplete(lpserver); if (dwErr != 0) { TRACE_RELEASE_WRITELOCK(lpserver); return INVALID_TRACEID; } } lpclient = TraceFindClient(lpserver, lpszCallerName); if (lpclient != NULL) { // // client already exists // TRACE_RELEASE_WRITELOCK(lpserver); return lpclient->TC_ClientID; } // // find an empty space // lplpcstart = lpserver->TS_ClientTable; lplpcend = lplpcstart + MAX_CLIENT_COUNT; for (lplpc = lplpcstart; lplpc < lplpcend; lplpc++) { if (*lplpc == NULL) { break; } } if (lplpc >= lplpcend) { // // no space in table // TRACE_RELEASE_WRITELOCK(lpserver); return INVALID_TRACEID; } // // create the new client and enable it // dwErr = TraceCreateClient(lplpc); if (dwErr != 0) { // // something wrong, so abort // TRACE_RELEASE_WRITELOCK(lpserver); return INVALID_TRACEID; } lpclient = *lplpc; lpclient->TC_ClientID = dwClientID = (DWORD)(lplpc - lplpcstart); lstrcpyn( lpclient->TC_ClientName, lpszCallerName, MAX_CLIENTNAME_LENGTH - 1 ); // // copy the client name in the other format as well // #ifdef UNICODE wcstombs( lpclient->TC_ClientNameA, lpclient->TC_ClientNameW, MAX_CLIENTNAME_LENGTH - 1 ); #else mbstowcs( lpclient->TC_ClientNameW, lpclient->TC_ClientNameA, MAX_CLIENTNAME_LENGTH - 1 ); #endif if ((dwFlags & TRACE_USE_FILE) || (dwFlags & TRACE_USE_CONSOLE)) { if (dwFlags & TRACE_USE_FILE) { lpclient->TC_Flags |= TRACEFLAGS_USEFILE; } if (dwFlags & TRACE_USE_CONSOLE) { lpclient->TC_Flags |= TRACEFLAGS_USECONSOLE; } } else { lpclient->TC_Flags |= TRACEFLAGS_REGCONFIG; } // // load client's configuration and open its file // and its console buffer if necessary // dwErr = TraceEnableClient(lpserver, lpclient, TRUE); if (dwErr != 0) { // // something wrong, so abort // TraceDeleteClient(lpserver, lplpc); TRACE_RELEASE_WRITELOCK(lpserver); return INVALID_TRACEID; } // // Create trace server thread if required // if (g_serverThread==NULL) { dwErr = TraceCreateServerThread(dwFlags, TRUE,TRUE); //have lock,check if (NO_ERROR != dwErr){ TRACE_RELEASE_WRITELOCK(lpserver); return INVALID_TRACEID; } } TRACE_RELEASE_WRITELOCK(lpserver); // // tell server there is a new client in the table // SetEvent(lpserver->TS_TableEvent); return dwClientID; } DWORD APIENTRY TraceDeregisterEx( IN DWORD dwTraceID, IN DWORD dwFlags ); // // called to stop tracing. // frees client state and notifies server of change // DWORD APIENTRY TraceDeregister( IN DWORD dwTraceID ) { return TraceDeregisterEx(dwTraceID, 0); } DWORD APIENTRY TraceDeregisterEx( IN DWORD dwTraceID, IN DWORD dwFlags ) { DWORD dwErr; LPTRACE_CLIENT *lplpc; LPTRACE_SERVER lpserver; if (dwTraceID == INVALID_TRACEID || dwTraceID >= MAX_CLIENT_COUNT) { return ERROR_INVALID_PARAMETER; } lpserver = GET_TRACE_SERVER_NO_INIT (); //ASSERTMSG ("Server not initialized ", lpserver); if (!ENTER_TRACE_API(lpserver)) { return ERROR_CAN_NOT_COMPLETE; } // // lock the server, unless the flag says not to. // if (!(dwFlags & TRACE_NO_SYNCH)) { TRACE_ACQUIRE_WRITELOCK(lpserver); } // // get the client pointer // lplpc = lpserver->TS_ClientTable + dwTraceID; dwErr = TraceDeleteClient(lpserver, lplpc); // // reset array for client change notifications. // only used if server thread is not created // if (!g_serverThread) { SetWaitArray(lpserver); } if (!(dwFlags & TRACE_NO_SYNCH)) { TRACE_RELEASE_WRITELOCK(lpserver); } // // tell the server that a client has left // SetEvent(lpserver->TS_TableEvent); return 0; } DWORD APIENTRY TraceGetConsole( IN DWORD dwTraceID, OUT LPHANDLE lphConsole ) { LPTRACE_CLIENT lpclient; LPTRACE_SERVER lpserver; if (dwTraceID == INVALID_TRACEID || dwTraceID >= MAX_CLIENT_COUNT || lphConsole == NULL) { return ERROR_INVALID_PARAMETER; } lpserver = GET_TRACE_SERVER_NO_INIT (); ASSERTMSG ("Server not initialized ", lpserver); if (!ENTER_TRACE_API(lpserver)) { return ERROR_CAN_NOT_COMPLETE; } *lphConsole = NULL; TRACE_ACQUIRE_READLOCK(lpserver); lpclient = lpserver->TS_ClientTable[dwTraceID]; if (lpclient == NULL) { TRACE_RELEASE_READLOCK(lpserver); return ERROR_INVALID_PARAMETER; } TRACE_ACQUIRE_READLOCK(lpclient); *lphConsole = lpclient->TC_Console; TRACE_RELEASE_READLOCK(lpclient); TRACE_RELEASE_READLOCK(lpserver); return 0; } DWORD APIENTRY TracePrintf( IN DWORD dwTraceID, IN LPCTSTR lpszFormat, IN ... OPTIONAL ) { DWORD dwSize; va_list arglist; if (dwTraceID == INVALID_TRACEID || dwTraceID >= MAX_CLIENT_COUNT) { return 0; } CREATE_SERVER_THREAD_IF_REQUIRED(); va_start(arglist, lpszFormat); dwSize = TraceVprintfInternal(dwTraceID, 0, lpszFormat, arglist); va_end(arglist); return dwSize; } DWORD APIENTRY TracePrintfEx( IN DWORD dwTraceID, IN DWORD dwFlags, IN LPCTSTR lpszFormat, IN ... OPTIONAL ) { DWORD dwSize; va_list arglist; if (dwTraceID == INVALID_TRACEID || dwTraceID >= MAX_CLIENT_COUNT) { return 0; } CREATE_SERVER_THREAD_IF_REQUIRED(); va_start(arglist, lpszFormat); dwSize = TraceVprintfInternal(dwTraceID, dwFlags, lpszFormat, arglist); va_end(arglist); return dwSize; } DWORD APIENTRY TraceVprintfEx( IN DWORD dwTraceID, IN DWORD dwFlags, IN LPCTSTR lpszFormat, IN va_list arglist ) { if (dwTraceID == INVALID_TRACEID || dwTraceID >= MAX_CLIENT_COUNT) { return 0; } CREATE_SERVER_THREAD_IF_REQUIRED(); return TraceVprintfInternal(dwTraceID, dwFlags, lpszFormat, arglist); } DWORD TraceVprintfInternal( IN DWORD dwTraceID, IN DWORD dwFlags, IN LPCTSTR lpszFormat, IN va_list arglist ) { SYSTEMTIME st; DWORD dwThread; DWORD dwErr, dwSize; LPTRACE_CLIENT lpclient; LPTRACE_SERVER lpserver; PTCHAR szFormat, szBuffer; lpserver = GET_TRACE_SERVER_NO_INIT (); ASSERTMSG ("Server not initialized ", lpserver); if (!ENTER_TRACE_API(lpserver)) { return ERROR_CAN_NOT_COMPLETE; } // // return quickly if no output will be generated; // if (dwFlags & TRACE_USE_MASK) { if (!(*(lpserver->TS_FlagsCache + dwTraceID) & (dwFlags & 0xffff0000))) { return 0; } } else { if (!*(lpserver->TS_FlagsCache + dwTraceID)) { return 0; } } TRACE_ACQUIRE_READLOCK(lpserver); lpclient = lpserver->TS_ClientTable[dwTraceID]; if (lpclient == NULL) { TRACE_RELEASE_READLOCK(lpserver); return 0; } TRACE_ACQUIRE_READLOCK(lpclient); if (TRACE_CLIENT_IS_DISABLED(lpclient)) { TRACE_RELEASE_READLOCK(lpclient); TRACE_RELEASE_READLOCK(lpserver); return 0; } szFormat = (PTCHAR) HeapAlloc(GetProcessHeap(), 0, DEF_PRINT_BUFSIZE); if (!szFormat) { TRACE_RELEASE_READLOCK(lpclient); TRACE_RELEASE_READLOCK(lpserver); return ERROR_NOT_ENOUGH_MEMORY; } szBuffer = (PTCHAR) HeapAlloc(GetProcessHeap(), 0, DEF_PRINT_BUFSIZE); if (!szBuffer) { TRACE_RELEASE_READLOCK(lpclient); TRACE_RELEASE_READLOCK(lpserver); HeapFree(GetProcessHeap(), 0, szFormat); return ERROR_NOT_ENOUGH_MEMORY; } // // default format for output is // \n