Skip to content

Commit 1bc7ac2

Browse files
committed
Improve block-to-IMP code on Windows.
This version will work with Windows Store apps. Patch by Dustin Howett!
1 parent e67d096 commit 1bc7ac2

File tree

1 file changed

+56
-10
lines changed

1 file changed

+56
-10
lines changed

block_to_imp.c

+56-10
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,61 @@ void __clear_cache(void* start, void* end);
3535
#include <nbutil.h>
3636
#endif
3737

38+
#ifdef _WIN32
39+
#include "safewindows.h"
40+
#if defined(WINAPI_FAMILY) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP && _WIN32_WINNT >= 0x0A00
41+
// Prefer the *FromApp versions when we're being built in a Windows Store App context on
42+
// Windows >= 10. *FromApp require the application to be manifested for "codeGeneration".
43+
#define VirtualAlloc VirtualAllocFromApp
44+
#define VirtualProtect VirtualProtectFromApp
45+
#endif // App family partition
46+
47+
#ifndef PROT_READ
48+
#define PROT_READ 0x4
49+
#endif
50+
51+
#ifndef PROT_WRITE
52+
#define PROT_WRITE 0x2
53+
#endif
54+
55+
#ifndef PROT_EXEC
56+
#define PROT_EXEC 0x1
57+
#endif
58+
59+
static void *valloc(size_t len)
60+
{
61+
return VirtualAlloc(NULL, len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
62+
}
63+
64+
static int mprotect(void *buffer, size_t len, int prot)
65+
{
66+
DWORD oldProt = 0, newProt = PAGE_NOACCESS;
67+
// Windows doesn't offer values that can be ORed together...
68+
if ((prot & PROT_WRITE))
69+
{
70+
// promote to readwrite as there's no writeonly protection constant
71+
newProt = PAGE_READWRITE;
72+
}
73+
else if ((prot & PROT_READ))
74+
{
75+
newProt = PAGE_READONLY;
76+
}
77+
78+
if ((prot & PROT_EXEC))
79+
{
80+
switch (newProt)
81+
{
82+
case PAGE_NOACCESS: newProt = PAGE_EXECUTE; break;
83+
case PAGE_READONLY: newProt = PAGE_EXECUTE_READ; break;
84+
case PAGE_READWRITE: newProt = PAGE_EXECUTE_READWRITE; break;
85+
}
86+
}
87+
88+
return 0 != VirtualProtect(buffer, len, newProt, &oldProt);
89+
}
90+
#endif // _WIN32
91+
92+
3893
#define PAGE_SIZE 4096
3994

4095
struct block_header
@@ -111,11 +166,7 @@ static struct trampoline_set *alloc_trampolines(char *start, char *end)
111166
{
112167
struct trampoline_set *metadata = calloc(1, sizeof(struct trampoline_set));
113168
metadata->buffers =
114-
#ifdef _WIN32
115-
VirtualAlloc(NULL, sizeof(struct trampoline_buffers), MEM_COMMIT, PAGE_READWRITE);
116-
#else
117-
valloc(sizeof(struct trampoline_buffers));
118-
#endif
169+
valloc(sizeof(struct trampoline_buffers));
119170
for (int i=0 ; i<HEADERS_PER_PAGE ; i++)
120171
{
121172
metadata->buffers->headers[i].fnptr = (void(*)(void))invalid;
@@ -124,12 +175,7 @@ static struct trampoline_set *alloc_trampolines(char *start, char *end)
124175
memcpy(block, start, end-start);
125176
}
126177
metadata->buffers->headers[HEADERS_PER_PAGE-1].block = NULL;
127-
#ifdef _WIN32
128-
DWORD ignored;
129-
VirtualProtect(metadata->buffers->rx_buffer, PAGE_SIZE, PAGE_EXECUTE_READ, &ignored);
130-
#else
131178
mprotect(metadata->buffers->rx_buffer, PAGE_SIZE, PROT_READ | PROT_EXEC);
132-
#endif
133179
clear_cache(metadata->buffers->rx_buffer, &metadata->buffers->rx_buffer[PAGE_SIZE]);
134180
return metadata;
135181
}

0 commit comments

Comments
 (0)