blob: 63c145cfab21de98eea1d44fe116bc75bf29ab16 [file] [log] [blame]
// Copyright 2016 The Crashpad Authors. All rights reserved.
//
// 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;
}