2 * winmisc.c: miscellaneous Windows-specific things
9 OSVERSIONINFO osVersion;
11 void platform_get_x11_auth(char *display, int *proto,
12 unsigned char *data, int *datalen)
14 /* We don't support this at all under Windows. */
17 const char platform_x11_best_transport[] = "localhost";
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"));
24 Filename filename_from_str(const char *str)
27 strncpy(ret.path, str, sizeof(ret.path));
28 ret.path[sizeof(ret.path)-1] = '\0';
32 const char *filename_to_str(const Filename *fn)
37 int filename_equal(Filename f1, Filename f2)
39 return !strcmp(f1.path, f2.path);
42 int filename_is_null(Filename fn)
47 char *get_username(void)
53 if (GetUserName(NULL, &namelen) == FALSE) {
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
62 user = snewn(namelen, char);
63 GetUserName(user, &namelen);
68 BOOL init_winver(void)
70 ZeroMemory(&osVersion, sizeof(osVersion));
71 osVersion.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
72 return GetVersionEx ( (OSVERSIONINFO *) &osVersion);
76 static FILE *debug_fp = NULL;
77 static HANDLE debug_hdl = INVALID_HANDLE_VALUE;
78 static int debug_got_console = 0;
84 if (!debug_got_console) {
86 debug_got_console = 1;
87 debug_hdl = GetStdHandle(STD_OUTPUT_HANDLE);
91 debug_fp = fopen("debug.log", "w");
94 if (debug_hdl != INVALID_HANDLE_VALUE) {
95 WriteFile(debug_hdl, buf, strlen(buf), &dw, NULL);
104 * Minefield - a Windows equivalent for Electric Fence
107 #define PAGESIZE 4096
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
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.
120 * Freeing anything causes instantaneous decommitment of the pages
121 * involved, so stale pointers are caught as soon as possible.
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;
132 static void minefield_admin_hide(int hide)
134 int access = hide ? PAGE_NOACCESS : PAGE_READWRITE;
135 VirtualProtect(minefield_admin, minefield_npages * 2, access, NULL);
138 static void minefield_init(void)
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)
150 minefield_size = size;
153 * Firstly, allocate a section of that to be the admin block.
154 * We'll need a two-byte field for each page.
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;
163 * Commit the admin region.
165 VirtualAlloc(minefield_admin, minefield_npages * 2,
166 MEM_COMMIT, PAGE_READWRITE);
169 * Mark all pages as unused (0xFFFF).
171 for (i = 0; i < minefield_npages; i++)
172 minefield_admin[i] = 0xFFFF;
175 * Hide the admin region.
177 minefield_admin_hide(1);
179 minefield_initialised = 1;
182 static void minefield_bomb(void)
184 div(1, *(int *) minefield_pages);
187 static void *minefield_alloc(int size)
190 int pos, lim, region_end, region_start;
194 npages = (size + PAGESIZE - 1) / PAGESIZE;
196 minefield_admin_hide(0);
199 * Search from current position until we find a contiguous
200 * bunch of npages+2 unused pages.
202 pos = minefield_curpos;
203 lim = minefield_npages;
205 /* Skip over used pages. */
206 while (pos < lim && minefield_admin[pos] != 0xFFFF)
208 /* Count unused pages. */
210 while (pos < lim && pos - start < npages + 2 &&
211 minefield_admin[pos] == 0xFFFF)
213 if (pos - start == npages + 2)
215 /* If we've reached the limit, reset the limit or stop. */
217 if (lim == minefield_npages) {
218 /* go round and start again at zero */
219 lim = minefield_curpos;
222 minefield_admin_hide(1);
228 minefield_curpos = pos - 1;
231 * We have npages+2 unused pages starting at start. We leave
232 * the first and last of these alone and use the rest.
234 region_end = (start + npages + 1) * PAGESIZE;
235 region_start = region_end - size;
236 /* FIXME: could align here if we wanted */
239 * Update the admin region.
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;
245 minefield_admin_hide(1);
247 VirtualAlloc((char *) minefield_pages + region_start, size,
248 MEM_COMMIT, PAGE_READWRITE);
249 return (char *) minefield_pages + region_start;
252 static void minefield_free(void *ptr)
254 int region_start, i, j;
256 minefield_admin_hide(0);
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)
263 for (j = i; j < minefield_npages && minefield_admin[j] != 0xFFFF; j++) {
264 minefield_admin[j] = 0xFFFF;
267 VirtualFree(ptr, j * PAGESIZE - region_start, MEM_DECOMMIT);
269 minefield_admin_hide(1);
272 static int minefield_get_size(void *ptr)
274 int region_start, i, j;
276 minefield_admin_hide(0);
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)
283 for (j = i; j < minefield_npages && minefield_admin[j] != 0xFFFF; j++);
285 minefield_admin_hide(1);
287 return j * PAGESIZE - region_start;
290 void *minefield_c_malloc(size_t size)
292 if (!minefield_initialised)
294 return minefield_alloc(size);
297 void minefield_c_free(void *p)
299 if (!minefield_initialised)
305 * realloc _always_ moves the chunk, for rapid detection of code
306 * that assumes it won't.
308 void *minefield_c_realloc(void *p, size_t size)
312 if (!minefield_initialised)
314 q = minefield_alloc(size);
315 oldsize = minefield_get_size(p);
316 memcpy(q, p, (oldsize < size ? oldsize : size));
321 #endif /* MINEFIELD */