Skip to content

Commit

Permalink
vNext
Browse files Browse the repository at this point in the history
- shmake now includes shim as a resource for self-containment
  • Loading branch information
aloneguid committed Sep 16, 2021
1 parent 16f04e9 commit c76637a
Show file tree
Hide file tree
Showing 16 changed files with 299 additions and 40 deletions.
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,19 @@ Download the latest release when ready.

## Building

As this is **Windows exclusive**, you need Visual Studio 2019 with Windows SDK installed. The main reason for this is `CMake` is considerably harder (but not impossible) to use when you need access to OS specific tools.
As this is **Windows exclusive**, you need Visual Studio 2019 with Windows SDK installed. Normally I would use CMake, but is considerably harder (not impossible) to use when you need access to OS specific tools, especially native resources (which I utilise heavily to do the magic).

`shmake` (but not shim) has dependency on:
- `boost::program_options`.
- `boost::program_options`.

All the dependencies are installed via [vcpkg](https://github.com/microsoft/vcpkg).

```
vcpkg install boost-program-options:x64-windows boost-program-options:x64-windows-static
```

`shim` does not have any dependencies and is kept as small and light as possible.

### Extra Oddness

`shmake` embeds `shim` inside it as a Windows native resource, so it's completely self-sufficient and can be distributed as a single `exe`. To do that, `smake`'s pre-build step copies `shim.exe` to `shim.bin` before build (as a pre-build step). Apparently `shim` is set as a project dependency of `shmake`, so it generates a full usable binary.
Binary file modified shim/shim.aps
Binary file not shown.
61 changes: 56 additions & 5 deletions shim/shim.cpp
Original file line number Diff line number Diff line change
@@ -1,19 +1,70 @@
#include <iostream>
#include <string>
#include "windows.h"
#include "resource.h"
#include "../shmake/resources.h"
#include "../shmake/util.h"

using namespace std;

#define MAX_LOADSTRING 1024
const wstring CMD_TOKEN = L"%s";

int main(int argc, char* argv)
int wmain(int argc, wchar_t* argv[])
{
resources res;
auto cmd_pattern = res.load_string(IDS_TARGET_CMDLINE);

auto cmdline = res.load_string(IDS_TARGET_CMDLINE);
wcout << "cmdline: " << cmd_pattern << endl;

wcout << "cmdline: " << cmdline << endl;
wstring cmd = cmd_pattern;

return 0;
if (argc > 1)
{
size_t pos = cmd.find(CMD_TOKEN);
if (pos != string::npos)
{
cmd.replace(pos, CMD_TOKEN.size(), argv[1]);
}
}

wcout << "final: " << cmd << endl;

STARTUPINFO si;
PROCESS_INFORMATION pi;

::ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);

::ZeroMemory(&pi, sizeof(pi));

if(!::CreateProcess(
NULL, // lpApplicationName
const_cast<LPWSTR>(cmd.c_str()),
NULL, // lpProcessAttributes
NULL, // lpThreadAttributes
TRUE, // bInheritHandles
NULL, // dwCreationFlags
NULL, // lpEnvironment
NULL, // lpCurrentDirectory
&si,
&pi))
{
wstring emsg = get_win32_last_error();
wcout << L"failed: " << emsg;
return 1;
}

wcout << L"waiting... ";
::WaitForSingleObject(pi.hProcess, INFINITE);
wcout << L"done." << endl;

DWORD exit_code = 0;
// if next line fails, code is still 0
::GetExitCodeProcess(pi.hProcess, &exit_code);

// free OS resources
::CloseHandle(pi.hProcess);
::CloseHandle(pi.hThread);

return exit_code;
}
2 changes: 1 addition & 1 deletion shim/shim.rc
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL

STRINGTABLE
BEGIN
IDS_TARGET_CMDLINE "vi %s"
IDS_TARGET_CMDLINE "notepad.exe %s"
END

#endif // Neutral resources
Expand Down
6 changes: 6 additions & 0 deletions shim/shim.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)out\</OutDir>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<VcpkgUseStatic>true</VcpkgUseStatic>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
Expand Down Expand Up @@ -138,6 +141,7 @@
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<LanguageStandard>stdcpp20</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
Expand All @@ -148,10 +152,12 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\shmake\resources.cpp" />
<ClCompile Include="..\shmake\util.cpp" />
<ClCompile Include="shim.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\shmake\resources.h" />
<ClInclude Include="..\shmake\util.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
Expand Down
Binary file added shmake/data.aps
Binary file not shown.
69 changes: 69 additions & 0 deletions shmake/data.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// English (United Kingdom) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE
BEGIN
"resource.h\0"
END

2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END

3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END

#endif // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// RCDATA
//

IDR_SHIM_EXE RCDATA "shim.bin"

#endif // English (United Kingdom) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

16 changes: 16 additions & 0 deletions shmake/resource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by data.rc
//
#define IDR_SHIM_EXE 102

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
32 changes: 26 additions & 6 deletions shmake/resources.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#include "resources.h"
#include <iostream>
#include "util.hpp"
#include "util.h"
#include <fstream>

#define MAX_LOADSTRING 1024

using namespace std;

resources::resources(const std::string& file_path)
resources::resources(const std::wstring& file_path)
: file_path { file_path }
{
if (file_path.empty())
Expand All @@ -15,7 +16,7 @@ resources::resources(const std::string& file_path)
}
else
{
if (!::LoadLibraryExA(file_path.c_str(), NULL, LOAD_LIBRARY_AS_DATAFILE))
if (!::LoadLibraryEx(file_path.c_str(), NULL, LOAD_LIBRARY_AS_DATAFILE))
throw_win32_le();
}
}
Expand Down Expand Up @@ -45,11 +46,11 @@ std::wstring resources::load_string(UINT id)

void resources::copy_main_icon(const resources& source)
{
HICON hSrcIcon = ::ExtractIconA(hInstance, file_path.c_str(), 0);
//HICON hSrcIcon = ::ExtractIconA(hInstance, file_path.c_str(), 0);

//::UpdateResource()

::DestroyIcon(hSrcIcon);
//::DestroyIcon(hSrcIcon);
}

void resources::replace_string_table(int index, const std::vector<std::wstring>& strings)
Expand All @@ -74,11 +75,30 @@ void resources::replace_string_table(int index, const std::vector<std::wstring>&
}
}

void resources::extract_binary_to_file(int res_id, const std::wstring& path)
{
// note that it is not necessary to free/unload any handles here

HRSRC hResInfo = ::FindResource(hInstance, MAKEINTRESOURCE(res_id), RT_RCDATA);
if (!hResInfo) throw_win32_le(L"find shim inside this module");

HGLOBAL hResData = ::LoadResource(hInstance, hResInfo);
if (!hResData) throw_win32_le(L"load shim resource");

size_t size = ::SizeofResource(hInstance, hResInfo);
LPVOID data = ::LockResource(hResData);

// write it out
ofstream f(path, ios::out | ios::binary);
f.write((char*)data, size);
f.close();
}

void resources::open_for_edit()
{
if (edit_made) return;

if (hEdit = ::BeginUpdateResourceA(file_path.c_str(), false))
if (hEdit = ::BeginUpdateResource(file_path.c_str(), false))
{
edit_made = true;
}
Expand Down
6 changes: 4 additions & 2 deletions shmake/resources.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
class resources
{
public:
resources(const std::string& file_path = "");
resources(const std::wstring& file_path = L"");
~resources();

std::wstring load_string(UINT id);
Expand All @@ -19,10 +19,12 @@ class resources

void replace_string_table(int index, const std::vector<std::wstring>& strings);

void extract_binary_to_file(int res_id, const std::wstring& path);

void commit_changes();

private:
std::string file_path;
std::wstring file_path;
HINSTANCE hInstance;
bool edit_made;
HANDLE hEdit;
Expand Down
Binary file added shmake/shim.bin
Binary file not shown.
Loading

0 comments on commit c76637a

Please sign in to comment.