michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /** michael@0: * LSPs are evil little bits of code that are allowed to inject into our michael@0: * networking stack by Windows. Once they have wormed into our process michael@0: * they gnaw at our innards until we crash. Here we force the buggers michael@0: * into the light by recording them in our crash information. michael@0: * We do the enumeration on a thread because I'm concerned about startup perf michael@0: * on machines with several LSPs. michael@0: */ michael@0: michael@0: #include "nsICrashReporter.h" michael@0: #include "nsISupportsImpl.h" michael@0: #include "nsServiceManagerUtils.h" michael@0: #include "nsThreadUtils.h" michael@0: #include michael@0: #include michael@0: michael@0: namespace mozilla { michael@0: namespace crashreporter { michael@0: michael@0: class LSPAnnotationGatherer : public nsRunnable michael@0: { michael@0: public: michael@0: NS_DECL_THREADSAFE_ISUPPORTS michael@0: NS_DECL_NSIRUNNABLE michael@0: michael@0: void Annotate(); michael@0: nsCString mString; michael@0: nsCOMPtr mThread; michael@0: }; michael@0: michael@0: NS_IMPL_ISUPPORTS(LSPAnnotationGatherer, nsIRunnable) michael@0: michael@0: void michael@0: LSPAnnotationGatherer::Annotate() michael@0: { michael@0: nsCOMPtr cr = michael@0: do_GetService("@mozilla.org/toolkit/crash-reporter;1"); michael@0: bool enabled; michael@0: if (cr && NS_SUCCEEDED(cr->GetEnabled(&enabled)) && enabled) { michael@0: cr->AnnotateCrashReport(NS_LITERAL_CSTRING("Winsock_LSP"), mString); michael@0: } michael@0: mThread->Shutdown(); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: LSPAnnotationGatherer::Run() michael@0: { michael@0: PR_SetCurrentThreadName("LSP Annotator"); michael@0: michael@0: mThread = NS_GetCurrentThread(); michael@0: michael@0: DWORD size = 0; michael@0: int err; michael@0: // Get the size of the buffer we need michael@0: if (SOCKET_ERROR != WSCEnumProtocols(nullptr, nullptr, &size, &err) || michael@0: err != WSAENOBUFS) { michael@0: // Er, what? michael@0: NS_NOTREACHED("WSCEnumProtocols suceeded when it should have failed ..."); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: nsAutoArrayPtr byteArray(new char[size]); michael@0: WSAPROTOCOL_INFOW* providers = michael@0: reinterpret_cast(byteArray.get()); michael@0: michael@0: int n = WSCEnumProtocols(nullptr, providers, &size, &err); michael@0: if (n == SOCKET_ERROR) { michael@0: // Lame. We provided the right size buffer; we'll just give up now. michael@0: NS_WARNING("Could not get LSP list"); michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: nsCString str; michael@0: for (int i = 0; i < n; i++) { michael@0: AppendUTF16toUTF8(nsDependentString(providers[i].szProtocol), str); michael@0: str.AppendLiteral(" : "); michael@0: str.AppendInt(providers[i].iVersion); michael@0: str.AppendLiteral(" : "); michael@0: str.AppendInt(providers[i].iSocketType); michael@0: str.AppendLiteral(" : "); michael@0: michael@0: wchar_t path[MAX_PATH]; michael@0: int dummy; michael@0: if (!WSCGetProviderPath(&providers[i].ProviderId, path, michael@0: &dummy, &err)) { michael@0: AppendUTF16toUTF8(nsDependentString(path), str); michael@0: } michael@0: michael@0: if (i + 1 != n) { michael@0: str.AppendLiteral(" \n "); michael@0: } michael@0: } michael@0: michael@0: mString = str; michael@0: NS_DispatchToMainThread(NS_NewRunnableMethod(this, &LSPAnnotationGatherer::Annotate)); michael@0: return NS_OK; michael@0: } michael@0: michael@0: void LSPAnnotate() michael@0: { michael@0: nsCOMPtr thread; michael@0: nsCOMPtr runnable = michael@0: do_QueryObject(new LSPAnnotationGatherer()); michael@0: NS_NewThread(getter_AddRefs(thread), runnable); michael@0: } michael@0: michael@0: } // namespace crashreporter michael@0: } // namespace mozilla