mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 09:27:59 +00:00
Move some of winmisc.c into winmiscs.c.
That's a terrible name, but winutils.c was already taken. The new source file is intended to be to winmisc.c as the new utils.c is to misc.c: it contains all the parts that are basically safe to link into _any_ Windows program (even standalone test things), without tying in to the runtime infrastructure of the main tools, referring to any other PuTTY source module, or introducing an extra Win32 API library dependency.
This commit is contained in:
parent
47ca2e98a5
commit
d4d89d51e9
7
Recipe
7
Recipe
@ -280,7 +280,7 @@ MISC = misc utils marshal memory
|
||||
MISCNETCOMMON = timing callback MISC version tree234 CONF
|
||||
MISCNET = MISCNETCOMMON be_misc settings proxy
|
||||
WINMISC = MISCNET winstore winnet winhandl cmdline windefs winmisc winproxy
|
||||
+ wintime winhsock errsock winsecur winucs miscucs
|
||||
+ wintime winhsock errsock winsecur winucs miscucs winmiscs
|
||||
UXMISCCOMMON = MISCNETCOMMON uxstore uxsel uxnet uxpeer uxmisc time
|
||||
+ uxfdsock errsock
|
||||
UXMISC = MISCNET UXMISCCOMMON uxproxy
|
||||
@ -332,13 +332,14 @@ psftp : [C] psftp winsftp wincons WINSSH BE_SSH SFTP wildcard WINMISC
|
||||
|
||||
pageant : [G] winpgnt pageant sshrsa sshpubk sshdes ARITH sshmd5 version
|
||||
+ tree234 MISC sshaes sshsha winsecur winpgntc aqsync sshdss sshsh256
|
||||
+ sshsh512 winutils sshecc winmisc winhelp conf pageant.res LIBS
|
||||
+ sshsh512 winutils sshecc winmisc winmiscs winhelp conf pageant.res
|
||||
+ LIBS
|
||||
|
||||
puttygen : [G] winpgen sshrsag sshdssg sshprime sshdes ARITH sshmd5 version
|
||||
+ sshrand winnoise sshsha winstore MISC winctrls sshrsa sshdss winmisc
|
||||
+ sshpubk sshaes sshsh256 sshsh512 IMPORT winutils puttygen.res
|
||||
+ tree234 notiming winhelp winnojmp CONF LIBS wintime sshecc
|
||||
+ sshecdsag winsecur
|
||||
+ sshecdsag winsecur winmiscs
|
||||
|
||||
pterm : [X] GTKTERM uxmisc misc ldisc settings uxpty uxsel BE_NONE uxstore
|
||||
+ uxsignal CHARSET cmdline uxpterm version time xpmpterm xpmptcfg
|
||||
|
@ -67,16 +67,6 @@ char filename_char_sanitise(char c)
|
||||
return c;
|
||||
}
|
||||
|
||||
#ifndef NO_SECUREZEROMEMORY
|
||||
/*
|
||||
* Windows implementation of smemclr (see misc.c) using SecureZeroMemory.
|
||||
*/
|
||||
void smemclr(void *b, size_t n) {
|
||||
if (b && n > 0)
|
||||
SecureZeroMemory(b, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
char *get_username(void)
|
||||
{
|
||||
DWORD namelen;
|
||||
@ -311,254 +301,6 @@ const char *win_strerror(int error)
|
||||
return es->text;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static FILE *debug_fp = NULL;
|
||||
static HANDLE debug_hdl = INVALID_HANDLE_VALUE;
|
||||
static int debug_got_console = 0;
|
||||
|
||||
void dputs(const char *buf)
|
||||
{
|
||||
DWORD dw;
|
||||
|
||||
if (!debug_got_console) {
|
||||
if (AllocConsole()) {
|
||||
debug_got_console = 1;
|
||||
debug_hdl = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
}
|
||||
}
|
||||
if (!debug_fp) {
|
||||
debug_fp = fopen("debug.log", "w");
|
||||
}
|
||||
|
||||
if (debug_hdl != INVALID_HANDLE_VALUE) {
|
||||
WriteFile(debug_hdl, buf, strlen(buf), &dw, NULL);
|
||||
}
|
||||
fputs(buf, debug_fp);
|
||||
fflush(debug_fp);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MINEFIELD
|
||||
/*
|
||||
* Minefield - a Windows equivalent for Electric Fence
|
||||
*/
|
||||
|
||||
#define PAGESIZE 4096
|
||||
|
||||
/*
|
||||
* Design:
|
||||
*
|
||||
* We start by reserving as much virtual address space as Windows
|
||||
* will sensibly (or not sensibly) let us have. We flag it all as
|
||||
* invalid memory.
|
||||
*
|
||||
* Any allocation attempt is satisfied by committing one or more
|
||||
* pages, with an uncommitted page on either side. The returned
|
||||
* memory region is jammed up against the _end_ of the pages.
|
||||
*
|
||||
* Freeing anything causes instantaneous decommitment of the pages
|
||||
* involved, so stale pointers are caught as soon as possible.
|
||||
*/
|
||||
|
||||
static int minefield_initialised = 0;
|
||||
static void *minefield_region = NULL;
|
||||
static long minefield_size = 0;
|
||||
static long minefield_npages = 0;
|
||||
static long minefield_curpos = 0;
|
||||
static unsigned short *minefield_admin = NULL;
|
||||
static void *minefield_pages = NULL;
|
||||
|
||||
static void minefield_admin_hide(int hide)
|
||||
{
|
||||
int access = hide ? PAGE_NOACCESS : PAGE_READWRITE;
|
||||
VirtualProtect(minefield_admin, minefield_npages * 2, access, NULL);
|
||||
}
|
||||
|
||||
static void minefield_init(void)
|
||||
{
|
||||
int size;
|
||||
int admin_size;
|
||||
int i;
|
||||
|
||||
for (size = 0x40000000; size > 0; size = ((size >> 3) * 7) & ~0xFFF) {
|
||||
minefield_region = VirtualAlloc(NULL, size,
|
||||
MEM_RESERVE, PAGE_NOACCESS);
|
||||
if (minefield_region)
|
||||
break;
|
||||
}
|
||||
minefield_size = size;
|
||||
|
||||
/*
|
||||
* Firstly, allocate a section of that to be the admin block.
|
||||
* We'll need a two-byte field for each page.
|
||||
*/
|
||||
minefield_admin = minefield_region;
|
||||
minefield_npages = minefield_size / PAGESIZE;
|
||||
admin_size = (minefield_npages * 2 + PAGESIZE - 1) & ~(PAGESIZE - 1);
|
||||
minefield_npages = (minefield_size - admin_size) / PAGESIZE;
|
||||
minefield_pages = (char *) minefield_region + admin_size;
|
||||
|
||||
/*
|
||||
* Commit the admin region.
|
||||
*/
|
||||
VirtualAlloc(minefield_admin, minefield_npages * 2,
|
||||
MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
/*
|
||||
* Mark all pages as unused (0xFFFF).
|
||||
*/
|
||||
for (i = 0; i < minefield_npages; i++)
|
||||
minefield_admin[i] = 0xFFFF;
|
||||
|
||||
/*
|
||||
* Hide the admin region.
|
||||
*/
|
||||
minefield_admin_hide(1);
|
||||
|
||||
minefield_initialised = 1;
|
||||
}
|
||||
|
||||
static void minefield_bomb(void)
|
||||
{
|
||||
div(1, *(int *) minefield_pages);
|
||||
}
|
||||
|
||||
static void *minefield_alloc(int size)
|
||||
{
|
||||
int npages;
|
||||
int pos, lim, region_end, region_start;
|
||||
int start;
|
||||
int i;
|
||||
|
||||
npages = (size + PAGESIZE - 1) / PAGESIZE;
|
||||
|
||||
minefield_admin_hide(0);
|
||||
|
||||
/*
|
||||
* Search from current position until we find a contiguous
|
||||
* bunch of npages+2 unused pages.
|
||||
*/
|
||||
pos = minefield_curpos;
|
||||
lim = minefield_npages;
|
||||
while (1) {
|
||||
/* Skip over used pages. */
|
||||
while (pos < lim && minefield_admin[pos] != 0xFFFF)
|
||||
pos++;
|
||||
/* Count unused pages. */
|
||||
start = pos;
|
||||
while (pos < lim && pos - start < npages + 2 &&
|
||||
minefield_admin[pos] == 0xFFFF)
|
||||
pos++;
|
||||
if (pos - start == npages + 2)
|
||||
break;
|
||||
/* If we've reached the limit, reset the limit or stop. */
|
||||
if (pos >= lim) {
|
||||
if (lim == minefield_npages) {
|
||||
/* go round and start again at zero */
|
||||
lim = minefield_curpos;
|
||||
pos = 0;
|
||||
} else {
|
||||
minefield_admin_hide(1);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
minefield_curpos = pos - 1;
|
||||
|
||||
/*
|
||||
* We have npages+2 unused pages starting at start. We leave
|
||||
* the first and last of these alone and use the rest.
|
||||
*/
|
||||
region_end = (start + npages + 1) * PAGESIZE;
|
||||
region_start = region_end - size;
|
||||
/* FIXME: could align here if we wanted */
|
||||
|
||||
/*
|
||||
* Update the admin region.
|
||||
*/
|
||||
for (i = start + 2; i < start + npages + 1; i++)
|
||||
minefield_admin[i] = 0xFFFE; /* used but no region starts here */
|
||||
minefield_admin[start + 1] = region_start % PAGESIZE;
|
||||
|
||||
minefield_admin_hide(1);
|
||||
|
||||
VirtualAlloc((char *) minefield_pages + region_start, size,
|
||||
MEM_COMMIT, PAGE_READWRITE);
|
||||
return (char *) minefield_pages + region_start;
|
||||
}
|
||||
|
||||
static void minefield_free(void *ptr)
|
||||
{
|
||||
int region_start, i, j;
|
||||
|
||||
minefield_admin_hide(0);
|
||||
|
||||
region_start = (char *) ptr - (char *) minefield_pages;
|
||||
i = region_start / PAGESIZE;
|
||||
if (i < 0 || i >= minefield_npages ||
|
||||
minefield_admin[i] != region_start % PAGESIZE)
|
||||
minefield_bomb();
|
||||
for (j = i; j < minefield_npages && minefield_admin[j] != 0xFFFF; j++) {
|
||||
minefield_admin[j] = 0xFFFF;
|
||||
}
|
||||
|
||||
VirtualFree(ptr, j * PAGESIZE - region_start, MEM_DECOMMIT);
|
||||
|
||||
minefield_admin_hide(1);
|
||||
}
|
||||
|
||||
static int minefield_get_size(void *ptr)
|
||||
{
|
||||
int region_start, i, j;
|
||||
|
||||
minefield_admin_hide(0);
|
||||
|
||||
region_start = (char *) ptr - (char *) minefield_pages;
|
||||
i = region_start / PAGESIZE;
|
||||
if (i < 0 || i >= minefield_npages ||
|
||||
minefield_admin[i] != region_start % PAGESIZE)
|
||||
minefield_bomb();
|
||||
for (j = i; j < minefield_npages && minefield_admin[j] != 0xFFFF; j++);
|
||||
|
||||
minefield_admin_hide(1);
|
||||
|
||||
return j * PAGESIZE - region_start;
|
||||
}
|
||||
|
||||
void *minefield_c_malloc(size_t size)
|
||||
{
|
||||
if (!minefield_initialised)
|
||||
minefield_init();
|
||||
return minefield_alloc(size);
|
||||
}
|
||||
|
||||
void minefield_c_free(void *p)
|
||||
{
|
||||
if (!minefield_initialised)
|
||||
minefield_init();
|
||||
minefield_free(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* realloc _always_ moves the chunk, for rapid detection of code
|
||||
* that assumes it won't.
|
||||
*/
|
||||
void *minefield_c_realloc(void *p, size_t size)
|
||||
{
|
||||
size_t oldsize;
|
||||
void *q;
|
||||
if (!minefield_initialised)
|
||||
minefield_init();
|
||||
q = minefield_alloc(size);
|
||||
oldsize = minefield_get_size(p);
|
||||
memcpy(q, p, (oldsize < size ? oldsize : size));
|
||||
minefield_free(p);
|
||||
return q;
|
||||
}
|
||||
|
||||
#endif /* MINEFIELD */
|
||||
|
||||
FontSpec *fontspec_new(const char *name, bool bold, int height, int charset)
|
||||
{
|
||||
FontSpec *f = snew(FontSpec);
|
||||
|
265
windows/winmiscs.c
Normal file
265
windows/winmiscs.c
Normal file
@ -0,0 +1,265 @@
|
||||
/*
|
||||
* winmiscs.c: Windows-specific standalone functions. Has the same
|
||||
* relationship to winmisc.c that utils.c does to misc.c, but the
|
||||
* corresponding name 'winutils.c' was already taken.
|
||||
*/
|
||||
|
||||
#include "putty.h"
|
||||
|
||||
#ifndef NO_SECUREZEROMEMORY
|
||||
/*
|
||||
* Windows implementation of smemclr (see misc.c) using SecureZeroMemory.
|
||||
*/
|
||||
void smemclr(void *b, size_t n) {
|
||||
if (b && n > 0)
|
||||
SecureZeroMemory(b, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
static FILE *debug_fp = NULL;
|
||||
static HANDLE debug_hdl = INVALID_HANDLE_VALUE;
|
||||
static int debug_got_console = 0;
|
||||
|
||||
void dputs(const char *buf)
|
||||
{
|
||||
DWORD dw;
|
||||
|
||||
if (!debug_got_console) {
|
||||
if (AllocConsole()) {
|
||||
debug_got_console = 1;
|
||||
debug_hdl = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
}
|
||||
}
|
||||
if (!debug_fp) {
|
||||
debug_fp = fopen("debug.log", "w");
|
||||
}
|
||||
|
||||
if (debug_hdl != INVALID_HANDLE_VALUE) {
|
||||
WriteFile(debug_hdl, buf, strlen(buf), &dw, NULL);
|
||||
}
|
||||
fputs(buf, debug_fp);
|
||||
fflush(debug_fp);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MINEFIELD
|
||||
/*
|
||||
* Minefield - a Windows equivalent for Electric Fence
|
||||
*/
|
||||
|
||||
#define PAGESIZE 4096
|
||||
|
||||
/*
|
||||
* Design:
|
||||
*
|
||||
* We start by reserving as much virtual address space as Windows
|
||||
* will sensibly (or not sensibly) let us have. We flag it all as
|
||||
* invalid memory.
|
||||
*
|
||||
* Any allocation attempt is satisfied by committing one or more
|
||||
* pages, with an uncommitted page on either side. The returned
|
||||
* memory region is jammed up against the _end_ of the pages.
|
||||
*
|
||||
* Freeing anything causes instantaneous decommitment of the pages
|
||||
* involved, so stale pointers are caught as soon as possible.
|
||||
*/
|
||||
|
||||
static int minefield_initialised = 0;
|
||||
static void *minefield_region = NULL;
|
||||
static long minefield_size = 0;
|
||||
static long minefield_npages = 0;
|
||||
static long minefield_curpos = 0;
|
||||
static unsigned short *minefield_admin = NULL;
|
||||
static void *minefield_pages = NULL;
|
||||
|
||||
static void minefield_admin_hide(int hide)
|
||||
{
|
||||
int access = hide ? PAGE_NOACCESS : PAGE_READWRITE;
|
||||
VirtualProtect(minefield_admin, minefield_npages * 2, access, NULL);
|
||||
}
|
||||
|
||||
static void minefield_init(void)
|
||||
{
|
||||
int size;
|
||||
int admin_size;
|
||||
int i;
|
||||
|
||||
for (size = 0x40000000; size > 0; size = ((size >> 3) * 7) & ~0xFFF) {
|
||||
minefield_region = VirtualAlloc(NULL, size,
|
||||
MEM_RESERVE, PAGE_NOACCESS);
|
||||
if (minefield_region)
|
||||
break;
|
||||
}
|
||||
minefield_size = size;
|
||||
|
||||
/*
|
||||
* Firstly, allocate a section of that to be the admin block.
|
||||
* We'll need a two-byte field for each page.
|
||||
*/
|
||||
minefield_admin = minefield_region;
|
||||
minefield_npages = minefield_size / PAGESIZE;
|
||||
admin_size = (minefield_npages * 2 + PAGESIZE - 1) & ~(PAGESIZE - 1);
|
||||
minefield_npages = (minefield_size - admin_size) / PAGESIZE;
|
||||
minefield_pages = (char *) minefield_region + admin_size;
|
||||
|
||||
/*
|
||||
* Commit the admin region.
|
||||
*/
|
||||
VirtualAlloc(minefield_admin, minefield_npages * 2,
|
||||
MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
/*
|
||||
* Mark all pages as unused (0xFFFF).
|
||||
*/
|
||||
for (i = 0; i < minefield_npages; i++)
|
||||
minefield_admin[i] = 0xFFFF;
|
||||
|
||||
/*
|
||||
* Hide the admin region.
|
||||
*/
|
||||
minefield_admin_hide(1);
|
||||
|
||||
minefield_initialised = 1;
|
||||
}
|
||||
|
||||
static void minefield_bomb(void)
|
||||
{
|
||||
div(1, *(int *) minefield_pages);
|
||||
}
|
||||
|
||||
static void *minefield_alloc(int size)
|
||||
{
|
||||
int npages;
|
||||
int pos, lim, region_end, region_start;
|
||||
int start;
|
||||
int i;
|
||||
|
||||
npages = (size + PAGESIZE - 1) / PAGESIZE;
|
||||
|
||||
minefield_admin_hide(0);
|
||||
|
||||
/*
|
||||
* Search from current position until we find a contiguous
|
||||
* bunch of npages+2 unused pages.
|
||||
*/
|
||||
pos = minefield_curpos;
|
||||
lim = minefield_npages;
|
||||
while (1) {
|
||||
/* Skip over used pages. */
|
||||
while (pos < lim && minefield_admin[pos] != 0xFFFF)
|
||||
pos++;
|
||||
/* Count unused pages. */
|
||||
start = pos;
|
||||
while (pos < lim && pos - start < npages + 2 &&
|
||||
minefield_admin[pos] == 0xFFFF)
|
||||
pos++;
|
||||
if (pos - start == npages + 2)
|
||||
break;
|
||||
/* If we've reached the limit, reset the limit or stop. */
|
||||
if (pos >= lim) {
|
||||
if (lim == minefield_npages) {
|
||||
/* go round and start again at zero */
|
||||
lim = minefield_curpos;
|
||||
pos = 0;
|
||||
} else {
|
||||
minefield_admin_hide(1);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
minefield_curpos = pos - 1;
|
||||
|
||||
/*
|
||||
* We have npages+2 unused pages starting at start. We leave
|
||||
* the first and last of these alone and use the rest.
|
||||
*/
|
||||
region_end = (start + npages + 1) * PAGESIZE;
|
||||
region_start = region_end - size;
|
||||
/* FIXME: could align here if we wanted */
|
||||
|
||||
/*
|
||||
* Update the admin region.
|
||||
*/
|
||||
for (i = start + 2; i < start + npages + 1; i++)
|
||||
minefield_admin[i] = 0xFFFE; /* used but no region starts here */
|
||||
minefield_admin[start + 1] = region_start % PAGESIZE;
|
||||
|
||||
minefield_admin_hide(1);
|
||||
|
||||
VirtualAlloc((char *) minefield_pages + region_start, size,
|
||||
MEM_COMMIT, PAGE_READWRITE);
|
||||
return (char *) minefield_pages + region_start;
|
||||
}
|
||||
|
||||
static void minefield_free(void *ptr)
|
||||
{
|
||||
int region_start, i, j;
|
||||
|
||||
minefield_admin_hide(0);
|
||||
|
||||
region_start = (char *) ptr - (char *) minefield_pages;
|
||||
i = region_start / PAGESIZE;
|
||||
if (i < 0 || i >= minefield_npages ||
|
||||
minefield_admin[i] != region_start % PAGESIZE)
|
||||
minefield_bomb();
|
||||
for (j = i; j < minefield_npages && minefield_admin[j] != 0xFFFF; j++) {
|
||||
minefield_admin[j] = 0xFFFF;
|
||||
}
|
||||
|
||||
VirtualFree(ptr, j * PAGESIZE - region_start, MEM_DECOMMIT);
|
||||
|
||||
minefield_admin_hide(1);
|
||||
}
|
||||
|
||||
static int minefield_get_size(void *ptr)
|
||||
{
|
||||
int region_start, i, j;
|
||||
|
||||
minefield_admin_hide(0);
|
||||
|
||||
region_start = (char *) ptr - (char *) minefield_pages;
|
||||
i = region_start / PAGESIZE;
|
||||
if (i < 0 || i >= minefield_npages ||
|
||||
minefield_admin[i] != region_start % PAGESIZE)
|
||||
minefield_bomb();
|
||||
for (j = i; j < minefield_npages && minefield_admin[j] != 0xFFFF; j++);
|
||||
|
||||
minefield_admin_hide(1);
|
||||
|
||||
return j * PAGESIZE - region_start;
|
||||
}
|
||||
|
||||
void *minefield_c_malloc(size_t size)
|
||||
{
|
||||
if (!minefield_initialised)
|
||||
minefield_init();
|
||||
return minefield_alloc(size);
|
||||
}
|
||||
|
||||
void minefield_c_free(void *p)
|
||||
{
|
||||
if (!minefield_initialised)
|
||||
minefield_init();
|
||||
minefield_free(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* realloc _always_ moves the chunk, for rapid detection of code
|
||||
* that assumes it won't.
|
||||
*/
|
||||
void *minefield_c_realloc(void *p, size_t size)
|
||||
{
|
||||
size_t oldsize;
|
||||
void *q;
|
||||
if (!minefield_initialised)
|
||||
minefield_init();
|
||||
q = minefield_alloc(size);
|
||||
oldsize = minefield_get_size(p);
|
||||
memcpy(q, p, (oldsize < size ? oldsize : size));
|
||||
minefield_free(p);
|
||||
return q;
|
||||
}
|
||||
|
||||
#endif /* MINEFIELD */
|
Loading…
Reference in New Issue
Block a user