]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - windows/winmisc.c
c8b92a60cbd2970749aa7e0ba466f9abf852a430
[PuTTY.git] / windows / winmisc.c
1 /*
2  * winmisc.c: miscellaneous Windows-specific things
3  */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include "putty.h"
8
9 OSVERSIONINFO osVersion;
10
11 void 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 }
16
17 const char platform_x11_best_transport[] = "localhost";
18
19 char *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
24 Filename filename_from_str(const char *str)
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
32 const char *filename_to_str(const Filename *fn)
33 {
34     return fn->path;
35 }
36
37 int filename_equal(Filename f1, Filename f2)
38 {
39     return !strcmp(f1.path, f2.path);
40 }
41
42 int filename_is_null(Filename fn)
43 {
44     return !*fn.path;
45 }
46
47 char *get_username(void)
48 {
49     DWORD namelen;
50     char *user;
51
52     namelen = 0;
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     }
61
62     user = snewn(namelen, char);
63     GetUserName(user, &namelen);
64
65     return user;
66 }
67
68 int SaneDialogBox(HINSTANCE hinst,
69                   LPCTSTR tmpl,
70                   HWND hwndparent,
71                   DLGPROC lpDialogFunc)
72 {
73     WNDCLASS wc;
74     HWND hwnd;
75     MSG msg;
76     int flags;
77     int ret;
78     int gm;
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
97     while ((gm=GetMessage(&msg, NULL, 0, 0)) > 0) {
98         flags=GetWindowLong(hwnd, BOXFLAGS);
99         if (!(flags & DF_END) && !IsDialogMessage(hwnd, &msg))
100             DispatchMessage(&msg);
101         if (flags & DF_END)
102             break;
103     }
104
105     if (gm == 0)
106         PostQuitMessage(msg.wParam); /* We got a WM_QUIT, pass it on */
107
108     ret=GetWindowLong(hwnd, BOXRESULT);
109     DestroyWindow(hwnd);
110     return ret;
111 }
112
113 void SaneEndDialog(HWND hwnd, int ret)
114 {
115     SetWindowLong(hwnd, BOXRESULT, ret);
116     SetWindowLong(hwnd, BOXFLAGS, DF_END);
117 }
118
119 BOOL init_winver(void)
120 {
121     ZeroMemory(&osVersion, sizeof(osVersion));
122     osVersion.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
123     return GetVersionEx ( (OSVERSIONINFO *) &osVersion);
124 }
125
126 #ifdef DEBUG
127 static FILE *debug_fp = NULL;
128 static HANDLE debug_hdl = INVALID_HANDLE_VALUE;
129 static int debug_got_console = 0;
130
131 void 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
175 static int minefield_initialised = 0;
176 static void *minefield_region = NULL;
177 static long minefield_size = 0;
178 static long minefield_npages = 0;
179 static long minefield_curpos = 0;
180 static unsigned short *minefield_admin = NULL;
181 static void *minefield_pages = NULL;
182
183 static 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
189 static 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
233 static void minefield_bomb(void)
234 {
235     div(1, *(int *) minefield_pages);
236 }
237
238 static 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
303 static 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
323 static 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
341 void *minefield_c_malloc(size_t size)
342 {
343     if (!minefield_initialised)
344         minefield_init();
345     return minefield_alloc(size);
346 }
347
348 void 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  */
359 void *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 */