win32.c (3853B)
1 /* 2 * Copyright (c) 2016 Kyle Milz <kyle@0x30.net> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 #include <direct.h> /* getcwd */ 17 #include <stdio.h> /* stderr */ 18 #include <windows.h> /* HANDLE, MapViewOfFile, ... */ 19 #include <io.h> 20 #define PATH_MAX 32000 21 22 #include "citrun.h" /* struct citrun_header */ 23 #include "os.h" 24 25 26 static HANDLE h = INVALID_HANDLE_VALUE; 27 28 static void 29 Err(int code, const char *fmt) 30 { 31 char buf[256]; 32 33 FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 34 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 256, NULL); 35 36 fprintf(stderr, "%s: %s", fmt, buf); 37 exit(code); 38 } 39 40 static HANDLE 41 mkstemp(char *template) 42 { 43 int i; 44 unsigned int r; 45 46 char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 47 48 for (i = strlen(template) - 1; i > 0; --i) { 49 if (template[i] != 'X') 50 break; 51 52 if (rand_s(&r)) { 53 fprintf(stderr, "rand failed: %s\n", strerror(errno)); 54 exit(1); 55 } 56 57 template[i] = chars[r % (sizeof(chars) - 1)]; 58 } 59 60 return CreateFile( 61 template, 62 GENERIC_READ | GENERIC_WRITE, 63 0, 64 NULL, 65 CREATE_NEW, 66 0, 67 NULL 68 ); 69 } 70 71 /* 72 * Extends the file and memory mapping length of fd by a requested amount of 73 * bytes (rounded up to the next page size). 74 * Returns a pointer to the extended region on success, exits on failure. 75 */ 76 void * 77 citrun_extend(size_t req_bytes) 78 { 79 size_t aligned_bytes; 80 size_t len; 81 HANDLE fm; 82 void *mem; 83 size_t page_mask; 84 85 SYSTEM_INFO system_info; 86 GetSystemInfo(&system_info); 87 88 page_mask = system_info.dwAllocationGranularity - 1; 89 aligned_bytes = (req_bytes + page_mask) & ~page_mask; 90 91 /* Get current file length. */ 92 if ((len = GetFileSize(h, NULL)) == INVALID_FILE_SIZE) 93 Err(1, "GetFileSize"); 94 95 /* Increase file pointer to new length. */ 96 if (SetFilePointer(h, len + aligned_bytes, NULL, FILE_BEGIN) 97 == INVALID_SET_FILE_POINTER) 98 Err(1, "SetFilePointer"); 99 100 /* Set new length. */ 101 if (SetEndOfFile(h) == 0) 102 Err(1, "SetEndOfFile"); 103 104 /* Create a new mapping that's used temporarily. */ 105 if ((fm = CreateFileMapping(h, NULL, PAGE_READWRITE, 0, 0, NULL)) == NULL) 106 Err(1, "CreateFileMapping"); 107 108 /* Create a new memory mapping for the newly extended space. */ 109 if ((mem = MapViewOfFile(fm, FILE_MAP_READ | FILE_MAP_WRITE, 0, len, req_bytes)) == NULL) 110 Err(1, "MapViewOfFile"); 111 112 CloseHandle(fm); 113 return mem; 114 } 115 116 /* 117 * Opens a file with a random suffix. Exits on error. 118 */ 119 void 120 citrun_open_fd() 121 { 122 char *procdir; 123 char procfile[PATH_MAX]; 124 125 if ((procdir = getenv("CITRUN_PROCDIR")) == NULL) 126 procdir = "C:\\CItRun"; 127 128 if (CreateDirectory(procdir, NULL) == 0 && 129 GetLastError() != ERROR_ALREADY_EXISTS) 130 Err(1, "CreateDirectory"); 131 132 strncpy(procfile, procdir, PATH_MAX); 133 strncat(procfile, "\\", PATH_MAX); 134 strncat(procfile, "program", PATH_MAX); 135 strncat(procfile, "_XXXXXXXXXX", PATH_MAX); 136 137 if ((h = mkstemp(procfile)) == INVALID_HANDLE_VALUE) 138 Err(1, "mkstemp"); 139 } 140 141 void 142 citrun_os_info(struct citrun_header *h) 143 { 144 h->pids[0] = getpid(); 145 146 if (GetModuleFileName(NULL, h->progname, sizeof(h->progname)) == 0) 147 Err(1, "GetModuleFileName"); 148 149 if (getcwd(h->cwd, sizeof(h->cwd)) == NULL) 150 strncpy(h->cwd, "", sizeof(h->cwd)); 151 }