2023-01-28 04:54:20 +00:00
|
|
|
|
// Copyright 2016 The Crashpad Authors
|
2022-04-02 01:21:55 +00:00
|
|
|
|
//
|
|
|
|
|
// 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;
|
|
|
|
|
}
|