]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - windows/winmisc.c
Move SaneDialogBox()/SaneEndDialog() from winmisc.c to windlg.c, since they
[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 BOOL init_winver(void)
69 {
70     ZeroMemory(&osVersion, sizeof(osVersion));
71     osVersion.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
72     return GetVersionEx ( (OSVERSIONINFO *) &osVersion);
73 }
74
75 #ifdef DEBUG
76 static FILE *debug_fp = NULL;
77 static HANDLE debug_hdl = INVALID_HANDLE_VALUE;
78 static int debug_got_console = 0;
79
80 void dputs(char *buf)
81 {
82     DWORD dw;
83
84     if (!debug_got_console) {
85         if (AllocConsole()) {
86             debug_got_console = 1;
87             debug_hdl = GetStdHandle(STD_OUTPUT_HANDLE);
88         }
89     }
90     if (!debug_fp) {
91         debug_fp = fopen("debug.log", "w");
92     }
93
94     if (debug_hdl != INVALID_HANDLE_VALUE) {
95         WriteFile(debug_hdl, buf, strlen(buf), &dw, NULL);
96     }
97     fputs(buf, debug_fp);
98     fflush(debug_fp);
99 }
100 #endif
101
102 #ifdef MINEFIELD
103 /*
104  * Minefield - a Windows equivalent for Electric Fence
105  */
106
107 #define PAGESIZE 4096
108
109 /*
110  * Design:
111  * 
112  * We start by reserving as much virtual address space as Windows
113  * will sensibly (or not sensibly) let us have. We flag it all as
114  * invalid memory.
115  * 
116  * Any allocation attempt is satisfied by committing one or more
117  * pages, with an uncommitted page on either side. The returned
118  * memory region is jammed up against the _end_ of the pages.
119  * 
120  * Freeing anything causes instantaneous decommitment of the pages
121  * involved, so stale pointers are caught as soon as possible.
122  */
123
124 static int minefield_initialised = 0;
125 static void *minefield_region = NULL;
126 static long minefield_size = 0;
127 static long minefield_npages = 0;
128 static long minefield_curpos = 0;
129 static unsigned short *minefield_admin = NULL;
130 static void *minefield_pages = NULL;
131
132 static void minefield_admin_hide(int hide)
133 {
134     int access = hide ? PAGE_NOACCESS : PAGE_READWRITE;
135     VirtualProtect(minefield_admin, minefield_npages * 2, access, NULL);
136 }
137
138 static void minefield_init(void)
139 {
140     int size;
141     int admin_size;
142     int i;
143
144     for (size = 0x40000000; size > 0; size = ((size >> 3) * 7) & ~0xFFF) {
145         minefield_region = VirtualAlloc(NULL, size,
146                                         MEM_RESERVE, PAGE_NOACCESS);
147         if (minefield_region)
148             break;
149     }
150     minefield_size = size;
151
152     /*
153      * Firstly, allocate a section of that to be the admin block.
154      * We'll need a two-byte field for each page.
155      */
156     minefield_admin = minefield_region;
157     minefield_npages = minefield_size / PAGESIZE;
158     admin_size = (minefield_npages * 2 + PAGESIZE - 1) & ~(PAGESIZE - 1);
159     minefield_npages = (minefield_size - admin_size) / PAGESIZE;
160     minefield_pages = (char *) minefield_region + admin_size;
161
162     /*
163      * Commit the admin region.
164      */
165     VirtualAlloc(minefield_admin, minefield_npages * 2,
166                  MEM_COMMIT, PAGE_READWRITE);
167
168     /*
169      * Mark all pages as unused (0xFFFF).
170      */
171     for (i = 0; i < minefield_npages; i++)
172         minefield_admin[i] = 0xFFFF;
173
174     /*
175      * Hide the admin region.
176      */
177     minefield_admin_hide(1);
178
179     minefield_initialised = 1;
180 }
181
182 static void minefield_bomb(void)
183 {
184     div(1, *(int *) minefield_pages);
185 }
186
187 static void *minefield_alloc(int size)
188 {
189     int npages;
190     int pos, lim, region_end, region_start;
191     int start;
192     int i;
193
194     npages = (size + PAGESIZE - 1) / PAGESIZE;
195
196     minefield_admin_hide(0);
197
198     /*
199      * Search from current position until we find a contiguous
200      * bunch of npages+2 unused pages.
201      */
202     pos = minefield_curpos;
203     lim = minefield_npages;
204     while (1) {
205         /* Skip over used pages. */
206         while (pos < lim && minefield_admin[pos] != 0xFFFF)
207             pos++;
208         /* Count unused pages. */
209         start = pos;
210         while (pos < lim && pos - start < npages + 2 &&
211                minefield_admin[pos] == 0xFFFF)
212             pos++;
213         if (pos - start == npages + 2)
214             break;
215         /* If we've reached the limit, reset the limit or stop. */
216         if (pos >= lim) {
217             if (lim == minefield_npages) {
218                 /* go round and start again at zero */
219                 lim = minefield_curpos;
220                 pos = 0;
221             } else {
222                 minefield_admin_hide(1);
223                 return NULL;
224             }
225         }
226     }
227
228     minefield_curpos = pos - 1;
229
230     /*
231      * We have npages+2 unused pages starting at start. We leave
232      * the first and last of these alone and use the rest.
233      */
234     region_end = (start + npages + 1) * PAGESIZE;
235     region_start = region_end - size;
236     /* FIXME: could align here if we wanted */
237
238     /*
239      * Update the admin region.
240      */
241     for (i = start + 2; i < start + npages + 1; i++)
242         minefield_admin[i] = 0xFFFE;   /* used but no region starts here */
243     minefield_admin[start + 1] = region_start % PAGESIZE;
244
245     minefield_admin_hide(1);
246
247     VirtualAlloc((char *) minefield_pages + region_start, size,
248                  MEM_COMMIT, PAGE_READWRITE);
249     return (char *) minefield_pages + region_start;
250 }
251
252 static void minefield_free(void *ptr)
253 {
254     int region_start, i, j;
255
256     minefield_admin_hide(0);
257
258     region_start = (char *) ptr - (char *) minefield_pages;
259     i = region_start / PAGESIZE;
260     if (i < 0 || i >= minefield_npages ||
261         minefield_admin[i] != region_start % PAGESIZE)
262         minefield_bomb();
263     for (j = i; j < minefield_npages && minefield_admin[j] != 0xFFFF; j++) {
264         minefield_admin[j] = 0xFFFF;
265     }
266
267     VirtualFree(ptr, j * PAGESIZE - region_start, MEM_DECOMMIT);
268
269     minefield_admin_hide(1);
270 }
271
272 static int minefield_get_size(void *ptr)
273 {
274     int region_start, i, j;
275
276     minefield_admin_hide(0);
277
278     region_start = (char *) ptr - (char *) minefield_pages;
279     i = region_start / PAGESIZE;
280     if (i < 0 || i >= minefield_npages ||
281         minefield_admin[i] != region_start % PAGESIZE)
282         minefield_bomb();
283     for (j = i; j < minefield_npages && minefield_admin[j] != 0xFFFF; j++);
284
285     minefield_admin_hide(1);
286
287     return j * PAGESIZE - region_start;
288 }
289
290 void *minefield_c_malloc(size_t size)
291 {
292     if (!minefield_initialised)
293         minefield_init();
294     return minefield_alloc(size);
295 }
296
297 void minefield_c_free(void *p)
298 {
299     if (!minefield_initialised)
300         minefield_init();
301     minefield_free(p);
302 }
303
304 /*
305  * realloc _always_ moves the chunk, for rapid detection of code
306  * that assumes it won't.
307  */
308 void *minefield_c_realloc(void *p, size_t size)
309 {
310     size_t oldsize;
311     void *q;
312     if (!minefield_initialised)
313         minefield_init();
314     q = minefield_alloc(size);
315     oldsize = minefield_get_size(p);
316     memcpy(q, p, (oldsize < size ? oldsize : size));
317     minefield_free(p);
318     return q;
319 }
320
321 #endif                          /* MINEFIELD */