Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,19 @@ if(TARGET secude_compat)
set_property(TARGET secude_compat PROPERTY INTERFACE_COMPILE_FEATURES "")
endif()
add_subdirectory(port/mfcwx)
# These libraries open files by paths CrypTool passes in Windows form; the app links mfcwx, which
# converts them, and the library tests use plain stubs.
foreach(target cryptool_analyse cryptool_cracklib)
target_compile_options(${target} PRIVATE "SHELL:-iquote ${CMAKE_SOURCE_DIR}/port/mfcwx/include"
"SHELL:-include ${CMAKE_SOURCE_DIR}/port/mfcwx/include/mfcwx/pathcompat.h")
endforeach()
add_library(mfcwx_path_stubs STATIC port/mfcwx/tests/path_stubs.cpp)
target_include_directories(mfcwx_path_stubs PRIVATE port/mfcwx/include)
foreach(test test_analyse test_cracklib)
if(TARGET ${test})
target_link_libraries(${test} PRIVATE mfcwx_path_stubs)
endif()
endforeach()
add_subdirectory(port/app)

option(CRYPTOOL_DIALOG_GALLERY "Build the dialog snapshot tool" OFF)
Expand Down
3 changes: 2 additions & 1 deletion port/app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ file(GLOB CT_EXTRA_SOURCES CONFIGURE_DEPENDS
${REPO_ROOT}/libVolRen/CQuaternion.cpp ${REPO_ROOT}/libVolRen/CVector.cpp ${REPO_ROOT}/libVolRen/Volume.cpp
${REPO_ROOT}/libVolRen/VolumeUtilities.cpp ${REPO_ROOT}/ChallengeResponse/*.cpp)

add_executable(CrypTool ${CT_SOURCES} ${CT_EXTRA_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/platform.cpp)
add_executable(CrypTool ${CT_SOURCES} ${CT_EXTRA_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/platform.cpp
${CMAKE_CURRENT_SOURCE_DIR}/miracl_rand.cpp)
mfcwx_add_rc(CrypTool RC ${CT_SRC}/CrypTool.rc MODULE CrypTool HEADERS ${CT_SRC}/resource.h
REPLACE "[CRYPTOOL_VERSION_FULL]=CrypTool ${PROJECT_VERSION}" "[CRYPTOOL_VERSION]=${PROJECT_VERSION}")

Expand Down
5 changes: 5 additions & 0 deletions port/app/miracl_rand.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Compiled without mfcwx/crtcompat.h: app code sees MIRACL's rand overloads renamed to mfcwx_rand.
#include "BIG.H"

Big mfcwx_rand(const Big& w) { return rand(w); }
Big mfcwx_rand(int n, int b) { return rand(n, b); }
12 changes: 12 additions & 0 deletions port/mfcwx/include/mfcwx/crtcompat.h
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,20 @@ int _findclose(intptr_t handle);
#define _findfirsti64 _findfirst
#define _findnexti64 _findnext

/* rand() of the Microsoft C runtime (per-thread LCG, RAND_MAX 0x7fff); CrypTool sizes buffers for it. */
int mfcwx_rand(void);
void mfcwx_srand(unsigned int seed);
#undef RAND_MAX
#define RAND_MAX 0x7fff
#define rand mfcwx_rand
#define srand mfcwx_srand

#endif /* _MFCWX_CRTCOMPAT */

#ifdef __cplusplus
}
namespace std {
using ::mfcwx_rand;
using ::mfcwx_srand;
}
#endif
17 changes: 17 additions & 0 deletions port/mfcwx/include/mfcwx/pathcompat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

// Force-included into third-party libraries that open files by paths coming from CrypTool,
// which are in Windows form ("\dir\file").

#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif
FILE* mfcwx_fopen(const char* name, const char* mode);
#ifdef __cplusplus
}
#include "mfcwx/fstreamcompat.h"
#endif

#define fopen mfcwx_fopen
13 changes: 13 additions & 0 deletions port/mfcwx/src/crt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -848,3 +848,16 @@ intptr_t _spawnl(int mode, const char* cmdname, const char* arg0, ...) {
CloseHandle(pi.hProcess);
return 0;
}

namespace {

thread_local unsigned int g_randSeed = 1;

} // namespace

extern "C" int mfcwx_rand(void) {
g_randSeed = g_randSeed * 214013u + 2531011u;
return static_cast<int>((g_randSeed >> 16) & 0x7fff);
}

extern "C" void mfcwx_srand(unsigned int seed) { g_randSeed = seed; }
103 changes: 103 additions & 0 deletions port/mfcwx/src/snapshot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#include <wx/toplevel.h>

#include <cstdlib>
#include <fstream>
#include <sstream>
#include <vector>

namespace mfcwx {

Expand Down Expand Up @@ -78,9 +81,109 @@ class SnapshotTimer : public wxTimer {
int m_round = 0;
};

std::string SafeName(const wxString& title) {
std::string name;
for (wxUniChar c : title)
name += (c.IsAscii() && isalnum(static_cast<int>(c.GetValue()))) ? static_cast<char>(c.GetValue()) : '_';
return name.substr(0, 40);
}

wxWindow* ActiveDialog() {
wxWindow* found = nullptr;
for (wxWindow* w : wxTopLevelWindows) {
auto* d = wxDynamicCast(w, wxDialog);
if (d && d->IsShown())
found = d;
}
return found;
}

// Development aid: MFCWX_AUTOMATION=file runs one step per line on a timer, for UI tests:
// command <id> WM_COMMAND to the main window
// button <id> WM_COMMAND (BN_CLICKED) to the topmost dialog
// text <id> <text> sets the text of a control of the topmost dialog
// wait <ms>
// snapshot <label> PNGs of all shown top-level windows into MFCWX_SNAPSHOT_DIR (or .)
// quit
class AutomationTimer : public wxTimer {
public:
AutomationTimer(std::vector<std::string> steps, std::string dir) : m_steps(std::move(steps)), m_dir(std::move(dir)) {}

void Notify() override {
if (m_waitUntil != 0 && wxGetLocalTimeMillis() < m_waitUntil)
return;
m_waitUntil = 0;
if (m_next >= m_steps.size()) {
fprintf(stderr, "mfcwx automation: done\n");
fflush(stderr);
_exit(0);
}
std::string line = m_steps[m_next++];
std::istringstream in(line);
std::string op;
in >> op;
fprintf(stderr, "mfcwx automation: %s\n", line.c_str());
if (op == "command" || op == "button") {
int id = 0;
in >> id;
CWnd* target = op == "command" ? AfxGetMainWnd() : WrapperFor(ActiveDialog());
if (target && target->m_hWnd)
target->PostMessage(WM_COMMAND, MAKEWPARAM(id, BN_CLICKED), 0);
else
fprintf(stderr, "mfcwx automation: no target window\n");
} else if (op == "text") {
int id = 0;
in >> id;
std::string text;
std::getline(in, text);
if (!text.empty() && text[0] == ' ')
text.erase(0, 1);
CWnd* dlg = WrapperFor(ActiveDialog());
if (dlg && dlg->m_hWnd)
::SetDlgItemText(dlg->m_hWnd, id, text.c_str());
} else if (op == "wait") {
long ms = 0;
in >> ms;
m_waitUntil = wxGetLocalTimeMillis() + ms;
} else if (op == "snapshot") {
std::string label;
in >> label;
int index = 0;
for (wxWindow* w : wxTopLevelWindows) {
if (!w->IsShown())
continue;
char path[1024];
snprintf(path, sizeof path, "%s/%s_%d_%s.png", m_dir.c_str(), label.c_str(), index++,
SafeName(w->GetLabel()).c_str());
bool ok = SnapshotWxWindow(w, path);
fprintf(stderr, "mfcwx snapshot %s %s\n", ok ? "saved" : "FAILED", path);
}
} else if (op == "quit") {
m_next = m_steps.size();
}
}

private:
std::vector<std::string> m_steps;
std::string m_dir;
size_t m_next = 0;
wxLongLong m_waitUntil = 0;
};

} // namespace

void StartSnapshotTimerFromEnvironment() {
if (const char* script = getenv("MFCWX_AUTOMATION")) {
std::ifstream f(script);
std::vector<std::string> steps;
for (std::string line; std::getline(f, line);)
if (!line.empty() && line[0] != '#')
steps.push_back(line);
const char* outDir = getenv("MFCWX_SNAPSHOT_DIR");
static AutomationTimer automation(steps, outDir && *outDir ? outDir : ".");
automation.Start(200);
return;
}
const char* dir = getenv("MFCWX_SNAPSHOT_DIR");
if (!dir || !*dir)
return;
Expand Down
9 changes: 6 additions & 3 deletions port/mfcwx/src/wnd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,10 @@ const CWnd wndNoTopMost;
CWnd::CWnd() : m_hWnd(nullptr) {}

CWnd::~CWnd() {
if (m_hWnd && IsMainThread()) {
if (!m_hWnd)
return;
// Wrappers destroyed on worker threads (dialogs run from AfxBeginThread) must detach too.
OnMain([this] {
wxWindow* w = GetWx();
WindowState* st = GetState(w);
if (st && st->permanent == this) {
Expand All @@ -730,7 +733,7 @@ CWnd::~CWnd() {
}
}
m_hWnd = nullptr;
}
});
}

CWnd* CWnd::FromWx(wxWindow* window) { return WrapperFor(window); }
Expand Down Expand Up @@ -1455,7 +1458,7 @@ CWnd* CWnd::SetActiveWindow() { return FromHandle(::SetActiveWindow(m_hWnd)); }
CWnd* CWnd::GetForegroundWindow() { return FromHandle(::GetForegroundWindow()); }
BOOL CWnd::SetForegroundWindow() { return ::SetForegroundWindow(m_hWnd); }
CWnd* CWnd::GetFocus() { return FromHandle(::GetFocus()); }
CWnd* CWnd::SetFocus() { return FromHandle(::SetFocus(m_hWnd)); }
CWnd* CWnd::SetFocus() { return FromHandle(::SetFocus(GetSafeHwnd())); }
CWnd* CWnd::GetDesktopWindow() { return nullptr; }
CWnd* CWnd::GetCapture() { return FromHandle(::GetCapture()); }
CWnd* CWnd::SetCapture() { return FromHandle(::SetCapture(m_hWnd)); }
Expand Down
12 changes: 12 additions & 0 deletions port/mfcwx/tests/path_stubs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <cstdio>
#include <string>

#include "mfcwx/codepage.h"

extern "C" FILE* mfcwx_fopen(const char* name, const char* mode) { return std::fopen(name, mode); }

namespace mfcwx {

std::string NativePath(const char* path) { return path ? path : ""; }

} // namespace mfcwx
Loading