119 lines
3.5 KiB
C++
119 lines
3.5 KiB
C++
// Copyright 2016 The Crashpad Authors
|
||
//
|
||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
// you may not use this file except in compliance with the License.
|
||
// You may obtain a copy of the License at
|
||
//
|
||
// http://www.apache.org/licenses/LICENSE-2.0
|
||
//
|
||
// Unless required by applicable law or agreed to in writing, software
|
||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
// See the License for the specific language governing permissions and
|
||
// limitations under the License.
|
||
|
||
#include <stdarg.h>
|
||
#include <stdlib.h>
|
||
#include <stdio.h>
|
||
#include <windows.h>
|
||
|
||
namespace {
|
||
|
||
// This custom logging function is to avoid taking a dependency on base in this
|
||
// standalone DLL. Don’t call this directly, use the LOG_FATAL() and
|
||
// PLOG_FATAL() macros below.
|
||
__declspec(noreturn) void LogFatal(const char* file,
|
||
int line,
|
||
bool get_last_error,
|
||
const char* format,
|
||
...) {
|
||
DWORD last_error = ERROR_SUCCESS;
|
||
if (get_last_error) {
|
||
last_error = GetLastError();
|
||
}
|
||
|
||
char fname[_MAX_FNAME];
|
||
char ext[_MAX_EXT];
|
||
if (_splitpath_s(file,
|
||
nullptr,
|
||
0,
|
||
nullptr,
|
||
0,
|
||
fname,
|
||
sizeof(fname),
|
||
ext,
|
||
sizeof(ext)) == 0) {
|
||
fprintf(stderr, "%s%s", fname, ext);
|
||
} else {
|
||
fputs(file, stderr);
|
||
}
|
||
fprintf(stderr, ":%d: ", line);
|
||
|
||
va_list va;
|
||
va_start(va, format);
|
||
vfprintf(stderr, format, va);
|
||
va_end(va);
|
||
|
||
if (get_last_error) {
|
||
fprintf(stderr, ": error %lu", last_error);
|
||
}
|
||
|
||
fputs("\n", stderr);
|
||
fflush(stderr);
|
||
|
||
TerminateProcess(GetCurrentProcess(), 1);
|
||
__fastfail(FAST_FAIL_FATAL_APP_EXIT);
|
||
}
|
||
|
||
#define LOG_FATAL(...) \
|
||
do { \
|
||
LogFatal(__FILE__, __LINE__, false, __VA_ARGS__); \
|
||
} while (false)
|
||
#define PLOG_FATAL(...) \
|
||
do { \
|
||
LogFatal(__FILE__, __LINE__, true, __VA_ARGS__); \
|
||
} while (false)
|
||
|
||
} // namespace
|
||
|
||
// This program intentionally blocks in DllMain which is executed with the
|
||
// loader lock locked. This allows us to test that
|
||
// CrashpadClient::DumpAndCrashTargetProcess() can still dump the target in this
|
||
// case.
|
||
BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID) {
|
||
switch (reason) {
|
||
case DLL_PROCESS_DETACH:
|
||
case DLL_THREAD_DETACH: {
|
||
// Recover the event handle stashed by the main executable.
|
||
static constexpr size_t kEventStringSize = 19;
|
||
wchar_t event_string[kEventStringSize];
|
||
SetLastError(ERROR_SUCCESS);
|
||
DWORD size = GetEnvironmentVariable(
|
||
L"CRASHPAD_TEST_DLL_EVENT", event_string, kEventStringSize);
|
||
if (size == 0 && GetLastError() != ERROR_SUCCESS) {
|
||
PLOG_FATAL("GetEnvironmentVariable");
|
||
}
|
||
if (size == 0 || size >= kEventStringSize) {
|
||
LOG_FATAL("GetEnvironmentVariable: size %u", size);
|
||
}
|
||
|
||
HANDLE event;
|
||
int converted = swscanf(event_string, L"%p", &event);
|
||
if (converted != 1) {
|
||
LOG_FATAL("swscanf: converted %d", converted);
|
||
}
|
||
|
||
// Let the main thread know that the loader lock is and will remain held.
|
||
if (!SetEvent(event)) {
|
||
PLOG_FATAL("SetEvent");
|
||
}
|
||
|
||
Sleep(INFINITE);
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|