citrun

watch C/C++ source code execute
Log | Files | Refs | LICENSE

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 }