1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 * LSPs are evil little bits of code that are allowed to inject into our
7 * networking stack by Windows. Once they have wormed into our process
8 * they gnaw at our innards until we crash. Here we force the buggers
9 * into the light by recording them in our crash information.
10 * We do the enumeration on a thread because I'm concerned about startup perf
11 * on machines with several LSPs.
14 #include "nsICrashReporter.h"
15 #include "nsISupportsImpl.h"
16 #include "nsServiceManagerUtils.h"
17 #include "nsThreadUtils.h"
18 #include "nsQueryObject.h"
19 #include "nsWindowsHelpers.h"
25 namespace crashreporter
{
27 class LSPAnnotationGatherer
: public Runnable
{
28 ~LSPAnnotationGatherer() {}
31 LSPAnnotationGatherer() : Runnable("crashreporter::LSPAnnotationGatherer") {}
38 void LSPAnnotationGatherer::Annotate() {
39 nsCOMPtr
<nsICrashReporter
> cr
=
40 do_GetService("@mozilla.org/toolkit/crash-reporter;1");
42 if (cr
&& NS_SUCCEEDED(cr
->GetCrashReporterEnabled(&enabled
)) && enabled
) {
43 cr
->AnnotateCrashReport("Winsock_LSP"_ns
, mString
);
48 LSPAnnotationGatherer::Run() {
51 // Get the size of the buffer we need
52 if (SOCKET_ERROR
!= WSCEnumProtocols(nullptr, nullptr, &size
, &err
) ||
55 MOZ_ASSERT_UNREACHABLE(
56 "WSCEnumProtocols succeeded when it should have "
58 return NS_ERROR_FAILURE
;
61 auto byteArray
= MakeUnique
<char[]>(size
);
62 WSAPROTOCOL_INFOW
* providers
=
63 reinterpret_cast<WSAPROTOCOL_INFOW
*>(byteArray
.get());
65 int n
= WSCEnumProtocols(nullptr, providers
, &size
, &err
);
66 if (n
== SOCKET_ERROR
) {
67 // Lame. We provided the right size buffer; we'll just give up now.
68 NS_WARNING("Could not get LSP list");
69 return NS_ERROR_FAILURE
;
73 for (int i
= 0; i
< n
; i
++) {
74 AppendUTF16toUTF8(nsDependentString(providers
[i
].szProtocol
), str
);
75 str
.AppendLiteral(" : ");
76 str
.AppendInt(providers
[i
].iVersion
);
77 str
.AppendLiteral(" : ");
78 str
.AppendInt(providers
[i
].iAddressFamily
);
79 str
.AppendLiteral(" : ");
80 str
.AppendInt(providers
[i
].iSocketType
);
81 str
.AppendLiteral(" : ");
82 str
.AppendInt(providers
[i
].iProtocol
);
83 str
.AppendLiteral(" : ");
84 str
.AppendPrintf("0x%lx", providers
[i
].dwServiceFlags1
);
85 str
.AppendLiteral(" : ");
86 str
.AppendPrintf("0x%lx", providers
[i
].dwProviderFlags
);
87 str
.AppendLiteral(" : ");
89 wchar_t path
[MAX_PATH
];
90 int pathLen
= MAX_PATH
;
91 if (!WSCGetProviderPath(&providers
[i
].ProviderId
, path
, &pathLen
, &err
)) {
92 AppendUTF16toUTF8(nsDependentString(path
), str
);
95 str
.AppendLiteral(" : ");
96 // Call WSCGetProviderInfo to obtain the category flags for this provider.
97 // When present, these flags inform Windows as to which order to chain the
100 size_t categoryInfoSize
= sizeof(categoryInfo
);
101 if (!WSCGetProviderInfo(&providers
[i
].ProviderId
, ProviderInfoLspCategories
,
102 (PBYTE
)&categoryInfo
, &categoryInfoSize
, 0, &err
)) {
103 str
.AppendPrintf("0x%lx", categoryInfo
);
106 str
.AppendLiteral(" : ");
107 if (providers
[i
].ProtocolChain
.ChainLen
<= BASE_PROTOCOL
) {
108 // If we're dealing with a catalog entry that identifies an individual
109 // base or layer provider, log its provider GUID.
110 RPC_CSTR provIdStr
= nullptr;
111 if (UuidToStringA(&providers
[i
].ProviderId
, &provIdStr
) == RPC_S_OK
) {
112 str
.Append(reinterpret_cast<char*>(provIdStr
));
113 RpcStringFreeA(&provIdStr
);
118 str
.AppendLiteral(" \n ");
123 NS_DispatchToMainThread(
124 NewRunnableMethod("crashreporter::LSPAnnotationGatherer::Annotate", this,
125 &LSPAnnotationGatherer::Annotate
));
130 nsCOMPtr
<nsIRunnable
> runnable(new LSPAnnotationGatherer());
131 NS_DispatchBackgroundTask(runnable
.forget());
134 } // namespace crashreporter
135 } // namespace mozilla