Skip to content

Commit

Permalink
Переделан диалог "О программе".
Browse files Browse the repository at this point in the history
Версионирование компонентов программы приведено к единому источнику.
Механизм выгрузки inject.dll доработан, чтобы она выгружалась из всех процессов.
  • Loading branch information
orefkov committed May 1, 2021
1 parent 689add8 commit 1e65648
Show file tree
Hide file tree
Showing 12 changed files with 221 additions and 13 deletions.
3 changes: 3 additions & 0 deletions src/include/core_as/version.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#define F_VERSION 1,0,0,6
#define P_VERSION "1.0.0.6"
#define COPY_RIGHT "© Александр Орефков, 2021"
20 changes: 15 additions & 5 deletions src/inject/dllmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ void getMyFolder(wchar_t* folder) {

// Функция загружает в процесс модули Core.As в случае если это задано в настройках
void testNeedLoad() {
// После приостановки и возобновлении подгрузки функция может вызываться для процесса,
// в который уже загружены модули. Если это так, то ничего не делаем.
if (GetModuleHandle(L"core_as.dll"))
return;
// При запуске стартера он готовит данные о загружаемых модулях и размещает их в shared memory
// Сейчас мы их получим
HANDLE hMemory = OpenFileMapping(FILE_MAP_READ, FALSE, LOAD_LIST_MEM_NAME);
Expand All @@ -52,6 +48,20 @@ void testNeedLoad() {
}
// Затем хэндл окна стартера
HWND hStarterWnd = reinterpret_cast<HWND>((size_t)*(unsigned*) (data + 4));
// При первом вызове надо передать в стартер описатель потока, чтобы при выключении
// он послал в него пустое сообщение, чтобы наша dll выгрузилась.
{
wchar_t buf[101];
swprintf(buf, 100, L"0 %d", GetCurrentThreadId());
SendMessage(hStarterWnd, WM_SETTEXT, 0, (LPARAM) buf);
}


// После приостановки и возобновлении подгрузки функция может вызываться для процесса,
// в который уже загружены модули. Если это так, то ничего не делаем.
if (GetModuleHandle(L"core_as.dll"))
return;

// Затем идет количество проверяемых модулей
unsigned modulesCount = *(unsigned*) (data + 8);
// Получим путь к нашей папке
Expand Down Expand Up @@ -139,7 +149,7 @@ void testNeedLoad() {
const wchar_t* defs = modul->defines? (const wchar_t*) (data + modul->defines) : nullptr;
if (coreModule->run(args, defs)) {
wchar_t buf[301];
swprintf(buf, 300, L"0 %d \"%s\" %s", hProcess, fileName, moduleName);
swprintf(buf, 300, L"1 %d \"%s\" %s", hProcess, fileName, moduleName);
SendMessage(hStarterWnd, WM_SETTEXT, 0, (LPARAM)buf);
}
}
Expand Down
Binary file modified src/inject/inject.rc
Binary file not shown.
1 change: 1 addition & 0 deletions src/modules/starter/src/ipc/ipc.as
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const string StarterWindowClassName = "Core.As.Starter";

// Коды видов сообщений
enum StarterMessages {
smInject, // Посылается при загрузке inject.dll в процесс, передает описатель потока
smLoadModule, // Посылается из inject.dll
smConnect, // Подключение модуля к стартеру, регистрирует его для посылки обратных сообщений
smDisconnect, // Отключение модуля от стартера
Expand Down
11 changes: 6 additions & 5 deletions src/runner/runner.rc
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,16 @@ END

#endif // APSTUDIO_INVOKED

#include "../include/core_as/version.h"

/////////////////////////////////////////////////////////////////////////////
//
// Version
//

VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,5
PRODUCTVERSION 1,0,0,5
FILEVERSION F_VERSION
PRODUCTVERSION F_VERSION
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
Expand All @@ -69,12 +70,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "��������� �������"
VALUE "FileDescription", "���������� ������� Core.As"
VALUE "FileVersion", "1.0.0.5"
VALUE "FileVersion", P_VERSION
VALUE "InternalName", "runner.exe"
VALUE "LegalCopyright", "(c) ��������� ������� 2020"
VALUE "LegalCopyright", COPY_RIGHT
VALUE "OriginalFilename", "runner.exe"
VALUE "ProductName", "������ ""Core.As"""
VALUE "ProductVersion", "1.0.0.5"
VALUE "ProductVersion", P_VERSION
END
END
BLOCK "VarFileInfo"
Expand Down
114 changes: 114 additions & 0 deletions src/starter/VersionInfo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* (c) Проект "Core.As", Александр Орефков [email protected]
* Чтение информации о версии
*/
#include "pch.h"
#include "VersionInfo.h"

VersionInfo::VersionInfo(const wchar_t* strFilePath, BOOL bFull) {
HINSTANCE hInst = GetModuleHandle(strFilePath);
if (hInst)
init(hInst, bFull);
else {
hInst = LoadLibraryEx(strFilePath, NULL, LOAD_LIBRARY_AS_DATAFILE);
if (hInst) {
init(hInst, bFull);
FreeLibrary(hInst);
}
}
}

VersionInfo::~VersionInfo() {
for (const auto p: m_blocks)
delete p;
}

void VersionInfo::init(HINSTANCE hInst, BOOL bFull) {
HRSRC hRes = FindResource(hInst, (LPCTSTR) 1, RT_VERSION);
if (!hRes)
return;
DWORD dwSize = SizeofResource(hInst, hRes);
if (!dwSize)
return;
HGLOBAL hData = LoadResource(hInst, hRes);
if (!hData)
return;
void* pData = LockResource(hData);
if (!pData) {
FreeResource(hData);
return;
}
unique_ptr<char> updata(new char[dwSize]);
char* m_pData = updata.get();
memcpy(m_pData, pData, dwSize);
UnlockResource(hData);
FreeResource(hData);

struct VS_BASE {
WORD wLength;
WORD wValueLength;
WORD wType;
wchar_t* GetText() {
return reinterpret_cast<wchar_t*>(this + 1);
}
};

struct VS_VERSIONINFO : VS_BASE {
wchar_t str[16];
WORD padding;
VS_FIXEDFILEINFO info;
};

struct StringFileInfo : VS_BASE {
wchar_t str[sizeof("StringFileInfo")];
};

struct StringTable : VS_BASE {
wchar_t str[sizeof("00000000")];
};

VS_VERSIONINFO* pVersion = reinterpret_cast<VS_VERSIONINFO*>(m_pData);
m_wFileVersion = *(uint64_t*) &pVersion->info.dwFileVersionMS;
m_wFileVersion = (m_wFileVersion >> 32) | (m_wFileVersion << 32);

m_wProdVersion = *(uint64_t*) &pVersion->info.dwProductVersionMS;
m_wProdVersion = (m_wProdVersion >> 32) | (m_wProdVersion << 32);
loaded = true;
if (!bFull)
return;

StringFileInfo* pSFI = reinterpret_cast<StringFileInfo*>(pVersion + 1);
if (pSFI->str[0] == L'S') { // StringFileInfo
StringTable* pTable = reinterpret_cast<StringTable*>(pSFI + 1);
StringTable* pTableEnd = reinterpret_cast<StringTable*>(reinterpret_cast<size_t>(pSFI) + pSFI->wLength);
while (pTable < pTableEnd) {
SBlockInfo* pBlock = new SBlockInfo;
m_blocks.push_back(pBlock);
pBlock->dwLangCP = 0;
wchar_t* ptr = pTable->str;
for (int i = 0; i < 8; i++, ptr++)
pBlock->dwLangCP = (pBlock->dwLangCP << 4) |
(*ptr < 'A' ? *ptr - '0' : (*ptr < 'a' ? *ptr - 'A' : *ptr - 'a') + 10);
VS_BASE* pString = reinterpret_cast<VS_BASE*>(pTable + 1);
VS_BASE* pStringEnd = reinterpret_cast<VS_BASE*>(reinterpret_cast<size_t>(pTable) + pTable->wLength);
while (pString < pStringEnd) {
wchar_t* pText = pString->GetText();
stringw key(e_s(pText));
if (pString->wValueLength) {
pText += key.length() + 1;
pText = reinterpret_cast<wchar_t*>((reinterpret_cast<size_t>(pText) + 3) & ~3);
} else
pText = nullptr;
pBlock->Names2Vals.emplace(move(key), e_s(pText));
pString = reinterpret_cast<VS_BASE*>((reinterpret_cast<size_t>(pString) + pString->wLength + 3) & ~3);
}
pTable = reinterpret_cast<StringTable*>((reinterpret_cast<size_t>(pTable) + pTable->wLength + 3) & ~3);
}
}
}

stringw VersionInfo::SBlockInfo::getStrLanguage() const {
return lstringsw<100>([=](wchar_t* p, unsigned s) {
return grow2(GetLocaleInfo(MAKELCID(dwLangCP >> 16, SORT_DEFAULT), LOCALE_SLANGUAGE, p, s +1), s);
});
}
47 changes: 47 additions & 0 deletions src/starter/VersionInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* (c) Проект "Core.As", Александр Орефков [email protected]
* Чтение информации о версии
*/
#pragma once

class VersionInfo {
public:
VersionInfo() = default;
VersionInfo(const wchar_t* strFilePath, BOOL bFull);

VersionInfo(HINSTANCE hInst, BOOL bFull) {
if (hInst)
init(hInst, bFull);
}

~VersionInfo();

struct SBlockInfo {
DWORD dwLangCP;
hashStrMapWIA<stringw> Names2Vals;
stringw getStrLanguage() const;
};

bool isLoaded() const {
return loaded;
}
uint64_t fileVersion() const {
return m_wFileVersion;
}
uint64_t prodVersion() const {
return m_wProdVersion;
}
size_t blocksCount() const {
return m_blocks.size();
}
SBlockInfo* block(unsigned dwIdx) const {
return m_blocks[dwIdx];
}

protected:
void init(HINSTANCE hInst, BOOL bFull);
vector<SBlockInfo*> m_blocks;
uint64_t m_wFileVersion;
uint64_t m_wProdVersion;
bool loaded{ false };
};
3 changes: 2 additions & 1 deletion src/starter/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#define IDI_STARTER 107
#define IDC_STARTER 109
#define IDR_MAINFRAME 128
#define IDC_VERSION 1000
#define ID_POPUP_32771 32771
#define ID_POPUP_32772 32772
#define ID_TOGGLE_INJECT 32773
Expand All @@ -24,7 +25,7 @@
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 129
#define _APS_NEXT_COMMAND_VALUE 32775
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 110
#endif
#endif
27 changes: 25 additions & 2 deletions src/starter/starter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "pch.h"
#include "starter.h"
#include "modules_list.h"
#include "VersionInfo.h"

UINT const WMAPP_NOTIFYCALLBACK = WM_APP + 1;
HWND hMainWnd;
Expand Down Expand Up @@ -106,9 +107,13 @@ void startInject64() {
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
UNREFERENCED_PARAMETER(lParam);
switch (message) {
case WM_INITDIALOG:
case WM_INITDIALOG: {
uint64_t version = VersionInfo(hMyInst, FALSE).prodVersion();
SetDlgItemText(hDlg, IDC_VERSION, lstringw<100>().s_format(L"%i.%i.%i.%i",
uint(version >> 48), uint((version>> 32) & 0xFFFF),
uint((version>> 16) & 0xFFFF), uint(version & 0xFFFF)));
return (INT_PTR) TRUE;

}
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
EndDialog(hDlg, LOWORD(wParam));
Expand Down Expand Up @@ -142,6 +147,7 @@ bool showNotify(ssw title, ssw msg) {
}

enum StarterMessages {
smInject, // Посылается при загрузке inject.dll в процесс, передает описатель потока
smLoadModule, // Посылается из inject.dll
smConnect, // Подключение модуля к стартеру, регистрирует его для посылки обратных сообщений
smDisconnect, // Отключение модуля от стартера
Expand All @@ -157,6 +163,12 @@ struct ConnectedInstance {
};

vector<ConnectedInstance> connectedInstances;
vector<DWORD> injectThreads;

// Ждем строку вида ThreadID
void processInject(SimpleStrNtW msg) {
injectThreads.push_back(wcstoul(msg, nullptr, 0));
}

// Ждем строку вида ИмяИнстанса\vHWND окна
void processConnect(SimpleStrNtW msg) {
Expand Down Expand Up @@ -204,6 +216,13 @@ void processStopInject() {
}
isInjected = false;
processBroadCast(lstringw<100>(+L"starter\v"_ss & (size_t)hMainWnd & L"\vinject=0"));
// При снятии хука inject.dll выгружается из других процессов не сразу, а когда
// через очередь сообщений потока с хуком пройдёт хотя бы одно сообщение.
// И для некоторых процессов это ожидание может сильно затянутся. Поэтому при снятии хука
// надо в каждый поток с inject.dll послать пустое сообщение.
for (auto threadId: injectThreads)
PostThreadMessage(threadId, WM_NULL, 0, 0);
injectThreads.clear();
}
}

Expand All @@ -225,6 +244,9 @@ void processMsgFromOther(const wchar_t* msg) {
if (*end == ' ')
++end;
switch (cmd) {
case smInject:
processInject(e_s(end));
break;
case smLoadModule:
break;
case smConnect:
Expand Down Expand Up @@ -393,6 +415,7 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int) {
DispatchMessage(&msg);
}
DeleteNotificationIcon();
processStopInject();
return (int) msg.wParam;
}

Expand Down
Binary file modified src/starter/starter.rc
Binary file not shown.
2 changes: 2 additions & 0 deletions src/starter/starter.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ exit 0
<ClInclude Include="Resource.h" />
<ClInclude Include="starter.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="VersionInfo.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="delay.cpp" />
Expand All @@ -257,6 +258,7 @@ exit 0
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="starter.cpp" />
<ClCompile Include="VersionInfo.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="starter.rc" />
Expand Down
6 changes: 6 additions & 0 deletions src/starter/starter.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
<ClInclude Include="modules_list.h">
<Filter>01 Основные</Filter>
</ClInclude>
<ClInclude Include="VersionInfo.h">
<Filter>03 Прочее</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="starter.cpp">
Expand All @@ -51,6 +54,9 @@
<ClCompile Include="delay.cpp">
<Filter>01 Основные</Filter>
</ClCompile>
<ClCompile Include="VersionInfo.cpp">
<Filter>03 Прочее</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Image Include="starter.ico">
Expand Down

0 comments on commit 1e65648

Please sign in to comment.