os_win32.c (4741B)
1 /* See LICENSE for license details. */ 2 #include <fileapi.h> 3 #include <handleapi.h> 4 #include <libloaderapi.h> 5 #include <memoryapi.h> 6 #include <sysinfoapi.h> 7 8 /* NOTE: copied from wtypes.h; we don't actually use this type but winbase.h needs it defined */ 9 typedef void *HWND; 10 #include <winbase.h> 11 12 #include "util.h" 13 14 #define OS_INVALID_FILE (INVALID_HANDLE_VALUE) 15 typedef HANDLE os_file; 16 typedef struct { 17 os_file file; 18 char *name; 19 } os_pipe; 20 21 typedef FILETIME os_filetime; 22 typedef HANDLE os_library_handle; 23 24 #define ERROR_FILE_STATS (os_file_stats){.timestamp = (os_filetime){0}, .filesize = -1} 25 typedef struct { 26 size filesize; 27 os_filetime timestamp; 28 } os_file_stats; 29 30 static Arena 31 os_alloc_arena(Arena a, size capacity) 32 { 33 SYSTEM_INFO Info; 34 GetSystemInfo(&Info); 35 36 if (capacity % Info.dwPageSize != 0) 37 capacity += (Info.dwPageSize - capacity % Info.dwPageSize); 38 39 size oldsize = a.end - a.beg; 40 if (oldsize > capacity) 41 return a; 42 43 if (a.beg) 44 VirtualFree(a.beg, oldsize, MEM_RELEASE); 45 46 a.beg = VirtualAlloc(0, capacity, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); 47 if (a.beg == NULL) 48 die("os_alloc_arena: couldn't allocate memory\n"); 49 a.end = a.beg + capacity; 50 return a; 51 } 52 53 static s8 54 os_read_file(Arena *a, char *fname, size fsize) 55 { 56 if (fsize > (size)U32_MAX) 57 die("os_read_file: %s\nHandling files >4GB is not yet " 58 "handled in win32 code\n", fname); 59 60 HANDLE h = CreateFileA(fname, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); 61 if (h == INVALID_HANDLE_VALUE) 62 die("os_read_file: couldn't open file: %s\n", fname); 63 64 s8 ret = s8alloc(a, fsize); 65 66 DWORD rlen = 0; 67 if (!ReadFile(h, ret.data, ret.len, &rlen, 0) && rlen != ret.len) 68 die("os_read_file: couldn't read file: %s\n", fname); 69 CloseHandle(h); 70 71 return ret; 72 } 73 74 static b32 75 os_write_file(char *fname, s8 raw) 76 { 77 if (raw.len > (size)U32_MAX) { 78 fputs("os_write_file: writing files > 4GB is not yet support on win32\n", stderr); 79 return 0; 80 } 81 82 HANDLE h = CreateFileA(fname, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); 83 if (h == INVALID_HANDLE_VALUE) 84 return 0; 85 86 DWORD wlen = 0; 87 WriteFile(h, raw.data, raw.len, &wlen, 0); 88 CloseHandle(h); 89 return wlen == raw.len; 90 } 91 92 static os_file_stats 93 os_get_file_stats(char *fname) 94 { 95 HANDLE h = CreateFileA(fname, 0, 0, 0, OPEN_EXISTING, 0, 0); 96 if (h == INVALID_HANDLE_VALUE) { 97 return ERROR_FILE_STATS; 98 } 99 100 BY_HANDLE_FILE_INFORMATION fileinfo; 101 if (!GetFileInformationByHandle(h, &fileinfo)) { 102 fputs("os_get_file_stats: couldn't get file info\n", stderr); 103 CloseHandle(h); 104 return ERROR_FILE_STATS; 105 } 106 CloseHandle(h); 107 108 size filesize = (size)fileinfo.nFileSizeHigh << 32; 109 filesize |= (size)fileinfo.nFileSizeLow; 110 return (os_file_stats){ 111 .filesize = filesize, 112 .timestamp = fileinfo.ftLastWriteTime, 113 }; 114 } 115 116 /* NOTE: win32 doesn't pollute the filesystem so no need to waste the user's time */ 117 static void 118 os_close_named_pipe(os_pipe p) 119 { 120 } 121 122 static os_pipe 123 os_open_named_pipe(char *name) 124 { 125 HANDLE h = CreateNamedPipeA(name, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE, 1, 126 0, 1 * MEGABYTE, 0, 0); 127 return (os_pipe){.file = h, .name = name}; 128 } 129 130 static b32 131 os_poll_pipe(os_pipe p) 132 { 133 DWORD bytes_available = 0; 134 return PeekNamedPipe(p.file, 0, 1 * MEGABYTE, 0, &bytes_available, 0) && bytes_available; 135 } 136 137 static size 138 os_read_pipe_data(os_pipe p, void *buf, size len) 139 { 140 DWORD total_read = 0; 141 ReadFile(p.file, buf, len, &total_read, 0); 142 return total_read; 143 } 144 145 static BeamformerParametersFull * 146 os_open_shared_memory_area(char *name) 147 { 148 HANDLE h = CreateFileMappingA(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 149 sizeof(BeamformerParametersFull), name); 150 if (h == INVALID_HANDLE_VALUE) 151 return NULL; 152 153 BeamformerParametersFull *new; 154 new = MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(*new)); 155 156 return new; 157 } 158 159 /* NOTE: closing the handle releases the memory and this happens when program terminates */ 160 static void 161 os_remove_shared_memory(char *name) 162 { 163 } 164 165 static os_library_handle 166 os_load_library(char *name, char *temp_name) 167 { 168 if (temp_name) { 169 if (CopyFile(name, temp_name, 0)) 170 name = temp_name; 171 } 172 173 os_library_handle res = LoadLibraryA(name); 174 if (!res) 175 TraceLog(LOG_WARNING, "os_load_library(%s): %d\n", name, GetLastError()); 176 177 if (temp_name) 178 DeleteFileA(temp_name); 179 180 return res; 181 } 182 183 static void * 184 os_lookup_dynamic_symbol(os_library_handle h, char *name) 185 { 186 if (!h) 187 return 0; 188 void *res = GetProcAddress(h, name); 189 if (!res) 190 TraceLog(LOG_WARNING, "os_lookup_dynamic_symbol(%s): %s\n", name, GetLastError()); 191 return res; 192 } 193 194 static void 195 os_unload_library(os_library_handle h) 196 { 197 FreeLibrary(h); 198 } 199 200 static b32 201 os_filetime_is_newer(os_filetime a, os_filetime b) 202 { 203 b32 result = CompareFileTime(&a, &b) > 0; 204 return result; 205 }