86 lines
2.8 KiB
C
86 lines
2.8 KiB
C
#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 <Windows.h>
|
|
|
|
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
|