Integrate unfix.org's IPv6 patches up to level 10, with rather a lot
[u/mdw/putty] / windows / winmisc.c
CommitLineData
e0e7dff8 1/*
f4ff9455 2 * winmisc.c: miscellaneous Windows-specific things
e0e7dff8 3 */
4
e0e7dff8 5#include <stdio.h>
6#include <stdlib.h>
7#include "putty.h"
8
4c48c989 9OSVERSIONINFO osVersion;
10
e0e7dff8 11void platform_get_x11_auth(char *display, int *proto,
12 unsigned char *data, int *datalen)
13{
14 /* We don't support this at all under Windows. */
15}
9a30e26b 16
fc0f17db 17const char platform_x11_best_transport[] = "localhost";
18
46ed7b64 19char *platform_get_x_display(void) {
20 /* We may as well check for DISPLAY in case it's useful. */
21 return dupstr(getenv("DISPLAY"));
22}
23
9fab77dc 24Filename filename_from_str(const char *str)
9a30e26b 25{
26 Filename ret;
27 strncpy(ret.path, str, sizeof(ret.path));
28 ret.path[sizeof(ret.path)-1] = '\0';
29 return ret;
30}
31
9fab77dc 32const char *filename_to_str(const Filename *fn)
9a30e26b 33{
9fab77dc 34 return fn->path;
9a30e26b 35}
36
37int filename_equal(Filename f1, Filename f2)
38{
39 return !strcmp(f1.path, f2.path);
40}
41
42int filename_is_null(Filename fn)
43{
44 return !*fn.path;
45}
d0912d1f 46
799dfcfa 47char *get_username(void)
48{
49 DWORD namelen;
50 char *user;
51
52 namelen = 0;
05581745 53 if (GetUserName(NULL, &namelen) == FALSE) {
54 /*
55 * Apparently this doesn't work at least on Windows XP SP2.
56 * Thus assume a maximum of 256. It will fail again if it
57 * doesn't fit.
58 */
59 namelen = 256;
60 }
799dfcfa 61
62 user = snewn(namelen, char);
63 GetUserName(user, &namelen);
64
65 return user;
66}
67
8ee3ff16 68int SaneDialogBox(HINSTANCE hinst,
69 LPCTSTR tmpl,
70 HWND hwndparent,
71 DLGPROC lpDialogFunc)
72{
2979718a 73 WNDCLASS wc;
74 HWND hwnd;
8ee3ff16 75 MSG msg;
2979718a 76 int flags;
77 int ret;
5e9e124a 78 int gm;
2979718a 79
80 wc.style = CS_DBLCLKS | CS_SAVEBITS | CS_BYTEALIGNWINDOW;
81 wc.lpfnWndProc = DefDlgProc;
82 wc.cbClsExtra = 0;
83 wc.cbWndExtra = DLGWINDOWEXTRA + 8;
84 wc.hInstance = hinst;
85 wc.hIcon = NULL;
86 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
87 wc.hbrBackground = (HBRUSH) (COLOR_BACKGROUND +1);
88 wc.lpszMenuName = NULL;
89 wc.lpszClassName = "PuTTYConfigBox";
90 RegisterClass(&wc);
91
92 hwnd = CreateDialog(hinst, tmpl, hwndparent, lpDialogFunc);
93
94 SetWindowLong(hwnd, BOXFLAGS, 0); /* flags */
95 SetWindowLong(hwnd, BOXRESULT, 0); /* result from SaneEndDialog */
96
5e9e124a 97 while ((gm=GetMessage(&msg, NULL, 0, 0)) > 0) {
2979718a 98 flags=GetWindowLong(hwnd, BOXFLAGS);
99 if (!(flags & DF_END) && !IsDialogMessage(hwnd, &msg))
8ee3ff16 100 DispatchMessage(&msg);
2979718a 101 if (flags & DF_END)
102 break;
8ee3ff16 103 }
2979718a 104
5e9e124a 105 if (gm == 0)
106 PostQuitMessage(msg.wParam); /* We got a WM_QUIT, pass it on */
107
2979718a 108 ret=GetWindowLong(hwnd, BOXRESULT);
109 DestroyWindow(hwnd);
110 return ret;
8ee3ff16 111}
112
113void SaneEndDialog(HWND hwnd, int ret)
114{
2979718a 115 SetWindowLong(hwnd, BOXRESULT, ret);
116 SetWindowLong(hwnd, BOXFLAGS, DF_END);
8ee3ff16 117}
118
4c48c989 119BOOL init_winver(void)
120{
121 ZeroMemory(&osVersion, sizeof(osVersion));
122 osVersion.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
123 return GetVersionEx ( (OSVERSIONINFO *) &osVersion);
124}
125
d0912d1f 126#ifdef DEBUG
127static FILE *debug_fp = NULL;
128static HANDLE debug_hdl = INVALID_HANDLE_VALUE;
129static int debug_got_console = 0;
130
131void dputs(char *buf)
132{
133 DWORD dw;
134
135 if (!debug_got_console) {
136 if (AllocConsole()) {
137 debug_got_console = 1;
138 debug_hdl = GetStdHandle(STD_OUTPUT_HANDLE);
139 }
140 }
141 if (!debug_fp) {
142 debug_fp = fopen("debug.log", "w");
143 }
144
145 if (debug_hdl != INVALID_HANDLE_VALUE) {
146 WriteFile(debug_hdl, buf, strlen(buf), &dw, NULL);
147 }
148 fputs(buf, debug_fp);
149 fflush(debug_fp);
150}
151#endif
152
153#ifdef MINEFIELD
154/*
155 * Minefield - a Windows equivalent for Electric Fence
156 */
157
158#define PAGESIZE 4096
159
160/*
161 * Design:
162 *
163 * We start by reserving as much virtual address space as Windows
164 * will sensibly (or not sensibly) let us have. We flag it all as
165 * invalid memory.
166 *
167 * Any allocation attempt is satisfied by committing one or more
168 * pages, with an uncommitted page on either side. The returned
169 * memory region is jammed up against the _end_ of the pages.
170 *
171 * Freeing anything causes instantaneous decommitment of the pages
172 * involved, so stale pointers are caught as soon as possible.
173 */
174
175static int minefield_initialised = 0;
176static void *minefield_region = NULL;
177static long minefield_size = 0;
178static long minefield_npages = 0;
179static long minefield_curpos = 0;
180static unsigned short *minefield_admin = NULL;
181static void *minefield_pages = NULL;
182
183static void minefield_admin_hide(int hide)
184{
185 int access = hide ? PAGE_NOACCESS : PAGE_READWRITE;
186 VirtualProtect(minefield_admin, minefield_npages * 2, access, NULL);
187}
188
189static void minefield_init(void)
190{
191 int size;
192 int admin_size;
193 int i;
194
195 for (size = 0x40000000; size > 0; size = ((size >> 3) * 7) & ~0xFFF) {
196 minefield_region = VirtualAlloc(NULL, size,
197 MEM_RESERVE, PAGE_NOACCESS);
198 if (minefield_region)
199 break;
200 }
201 minefield_size = size;
202
203 /*
204 * Firstly, allocate a section of that to be the admin block.
205 * We'll need a two-byte field for each page.
206 */
207 minefield_admin = minefield_region;
208 minefield_npages = minefield_size / PAGESIZE;
209 admin_size = (minefield_npages * 2 + PAGESIZE - 1) & ~(PAGESIZE - 1);
210 minefield_npages = (minefield_size - admin_size) / PAGESIZE;
211 minefield_pages = (char *) minefield_region + admin_size;
212
213 /*
214 * Commit the admin region.
215 */
216 VirtualAlloc(minefield_admin, minefield_npages * 2,
217 MEM_COMMIT, PAGE_READWRITE);
218
219 /*
220 * Mark all pages as unused (0xFFFF).
221 */
222 for (i = 0; i < minefield_npages; i++)
223 minefield_admin[i] = 0xFFFF;
224
225 /*
226 * Hide the admin region.
227 */
228 minefield_admin_hide(1);
229
230 minefield_initialised = 1;
231}
232
233static void minefield_bomb(void)
234{
235 div(1, *(int *) minefield_pages);
236}
237
238static void *minefield_alloc(int size)
239{
240 int npages;
241 int pos, lim, region_end, region_start;
242 int start;
243 int i;
244
245 npages = (size + PAGESIZE - 1) / PAGESIZE;
246
247 minefield_admin_hide(0);
248
249 /*
250 * Search from current position until we find a contiguous
251 * bunch of npages+2 unused pages.
252 */
253 pos = minefield_curpos;
254 lim = minefield_npages;
255 while (1) {
256 /* Skip over used pages. */
257 while (pos < lim && minefield_admin[pos] != 0xFFFF)
258 pos++;
259 /* Count unused pages. */
260 start = pos;
261 while (pos < lim && pos - start < npages + 2 &&
262 minefield_admin[pos] == 0xFFFF)
263 pos++;
264 if (pos - start == npages + 2)
265 break;
266 /* If we've reached the limit, reset the limit or stop. */
267 if (pos >= lim) {
268 if (lim == minefield_npages) {
269 /* go round and start again at zero */
270 lim = minefield_curpos;
271 pos = 0;
272 } else {
273 minefield_admin_hide(1);
274 return NULL;
275 }
276 }
277 }
278
279 minefield_curpos = pos - 1;
280
281 /*
282 * We have npages+2 unused pages starting at start. We leave
283 * the first and last of these alone and use the rest.
284 */
285 region_end = (start + npages + 1) * PAGESIZE;
286 region_start = region_end - size;
287 /* FIXME: could align here if we wanted */
288
289 /*
290 * Update the admin region.
291 */
292 for (i = start + 2; i < start + npages + 1; i++)
293 minefield_admin[i] = 0xFFFE; /* used but no region starts here */
294 minefield_admin[start + 1] = region_start % PAGESIZE;
295
296 minefield_admin_hide(1);
297
298 VirtualAlloc((char *) minefield_pages + region_start, size,
299 MEM_COMMIT, PAGE_READWRITE);
300 return (char *) minefield_pages + region_start;
301}
302
303static void minefield_free(void *ptr)
304{
305 int region_start, i, j;
306
307 minefield_admin_hide(0);
308
309 region_start = (char *) ptr - (char *) minefield_pages;
310 i = region_start / PAGESIZE;
311 if (i < 0 || i >= minefield_npages ||
312 minefield_admin[i] != region_start % PAGESIZE)
313 minefield_bomb();
314 for (j = i; j < minefield_npages && minefield_admin[j] != 0xFFFF; j++) {
315 minefield_admin[j] = 0xFFFF;
316 }
317
318 VirtualFree(ptr, j * PAGESIZE - region_start, MEM_DECOMMIT);
319
320 minefield_admin_hide(1);
321}
322
323static int minefield_get_size(void *ptr)
324{
325 int region_start, i, j;
326
327 minefield_admin_hide(0);
328
329 region_start = (char *) ptr - (char *) minefield_pages;
330 i = region_start / PAGESIZE;
331 if (i < 0 || i >= minefield_npages ||
332 minefield_admin[i] != region_start % PAGESIZE)
333 minefield_bomb();
334 for (j = i; j < minefield_npages && minefield_admin[j] != 0xFFFF; j++);
335
336 minefield_admin_hide(1);
337
338 return j * PAGESIZE - region_start;
339}
340
341void *minefield_c_malloc(size_t size)
342{
343 if (!minefield_initialised)
344 minefield_init();
345 return minefield_alloc(size);
346}
347
348void minefield_c_free(void *p)
349{
350 if (!minefield_initialised)
351 minefield_init();
352 minefield_free(p);
353}
354
355/*
356 * realloc _always_ moves the chunk, for rapid detection of code
357 * that assumes it won't.
358 */
359void *minefield_c_realloc(void *p, size_t size)
360{
361 size_t oldsize;
362 void *q;
363 if (!minefield_initialised)
364 minefield_init();
365 q = minefield_alloc(size);
366 oldsize = minefield_get_size(p);
367 memcpy(q, p, (oldsize < size ? oldsize : size));
368 minefield_free(p);
369 return q;
370}
371
372#endif /* MINEFIELD */