#if COMPILER_MSVC /* ========================== * * Msvc RC file lookup * ========================== */ #include "incbin.h" #include "scratch.h" #include "string.h" #include "atomic.h" #include "intrinsics.h" #define WIN32_LEAN_AND_MEAN #define UNICODE #include struct rc_search_params { /* In */ struct string name_lower; /* Out */ b32 found; struct string data; }; /* Find first resource with `type` and return the data in `udata`. */ INTERNAL BOOL CALLBACK enum_func(HMODULE module, LPCWSTR type, LPCWSTR wstr_entry_name, LONG_PTR udata) { struct arena_temp scratch = scratch_begin_no_conflict(); struct rc_search_params *params = (struct rc_search_params *)udata; struct string entry_name_lower = string_lower(scratch.arena, string_from_wstr_no_limit(scratch.arena, (LPWSTR)wstr_entry_name)); params->found = false; params->data = STRING(0, 0); if (string_eq(entry_name_lower, params->name_lower)) { HRSRC hres = FindResourceW(module, wstr_entry_name, type); if (hres) { HGLOBAL hg = LoadResource(module, hres); if (hg) { params->found = true; params->data.len = SizeofResource(module, hres); params->data.text = LockResource(hg); } } } scratch_end(scratch); return !params->found; } struct string _incbin_get(struct _incbin_rc_resource *inc) { enum _incbin_state state = atomic_i32_eval(&inc->state); if (state != INCBIN_STATE_SEARCHED) { struct arena_temp scratch = scratch_begin_no_conflict(); if (state == INCBIN_STATE_UNSEARCHED) { enum _incbin_state v = atomic_i32_eval_compare_exchange(&inc->state, state, INCBIN_STATE_SEARCHING); if (v == state) { /* Search RC file for the resource name */ struct string name_lower = string_lower(scratch.arena, inc->rc_name); struct rc_search_params params = { .name_lower = name_lower }; EnumResourceNamesW(NULL, RT_RCDATA, &enum_func, (LONG_PTR)¶ms); if (!params.found) { sys_panic(string_format(scratch.arena, LIT("INCBIN include not found in RC file: \"%F\""), FMT_STR(inc->rc_name))); } inc->data = params.data; state = INCBIN_STATE_SEARCHED; atomic_i32_eval_exchange(&inc->state, state); } else { state = v; } } /* Spin while another thread searches */ while (state != INCBIN_STATE_SEARCHED) { ix_pause(); state = atomic_i32_eval(&inc->state); } scratch_end(scratch); } return inc->data; } #endif