1
0
forked from 0ad/0ad

# overhauled error handling; made sure all low-level function failures are caught at the source.

* replace all "return ERR_*" with WARN_RETURN(ERR_*) - makes sure
function failures are noticed *at the cause*, not later
* LibError_from_* now take bool warn_if_failed param
* replace more debug_warns with dedicated error codes (allows localized
error reports and doesn't spam the EXE with strings)

This was SVN commit r3722.
This commit is contained in:
janwas 2006-04-03 01:00:45 +00:00
parent 001e951066
commit 5738bd4820
37 changed files with 401 additions and 363 deletions

View File

@ -52,7 +52,7 @@ void* single_calloc(void* storage, volatile uintptr_t* in_use_flag, size_t size)
p = malloc(size);
if(!p)
{
debug_warn("out of memory");
WARN_ERR(ERR_NO_MEM);
return 0;
}
}
@ -150,11 +150,11 @@ static LibError validate_da(DynArray* da)
// very thin wrapper on top of sys/mman.h that makes the intent more obvious
// (its commit/decommit semantics are difficult to tell apart).
static inline LibError LibError_from_mmap(void* ret)
static inline LibError LibError_from_mmap(void* ret, bool warn_if_failed = true)
{
if(ret != MAP_FAILED)
return ERR_OK;
return LibError_from_errno();
return LibError_from_errno(warn_if_failed);
}
static const int mmap_flags = MAP_PRIVATE|MAP_ANONYMOUS;
@ -170,7 +170,8 @@ static LibError mem_reserve(size_t size, u8** pp)
static LibError mem_release(u8* p, size_t size)
{
errno = 0;
return LibError_from_posix(munmap(p, size));
int ret = munmap(p, size);
return LibError_from_posix(ret);
}
static LibError mem_commit(u8* p, size_t size, int prot)
@ -194,7 +195,8 @@ static LibError mem_decommit(u8* p, size_t size)
static LibError mem_protect(u8* p, size_t size, int prot)
{
errno = 0;
return LibError_from_posix(mprotect(p, size, prot));
int ret = mprotect(p, size, prot);
return LibError_from_posix(ret);
}
@ -270,10 +272,7 @@ LibError da_set_size(DynArray* da, size_t new_size)
CHECK_DA(da);
if(da->prot & DA_NOT_OUR_MEM)
{
debug_warn("da is marked DA_NOT_OUR_MEM, must not be altered");
return ERR_LOGIC;
}
WARN_RETURN(ERR_LOGIC);
// determine how much to add/remove
const size_t cur_size_pa = round_up_to_page(da->cur_size);
@ -284,7 +283,7 @@ LibError da_set_size(DynArray* da, size_t new_size)
// note: do not complain - some allocators (e.g. file_cache)
// egitimately use up all available space.
if(new_size_pa > da->max_size_pa)
return ERR_LIMIT;
return ERR_LIMIT; // NOWARN
u8* end = da->base + cur_size_pa;
// expanding
@ -327,10 +326,7 @@ LibError da_set_prot(DynArray* da, int prot)
// somewhat more subtle: POSIX mprotect requires the memory have been
// mmap-ed, which it probably wasn't here.
if(da->prot & DA_NOT_OUR_MEM)
{
debug_warn("da is marked DA_NOT_OUR_MEM, must not be altered");
return ERR_LOGIC;
}
WARN_RETURN(ERR_LOGIC);
da->prot = prot;
CHECK_ERR(mem_protect(da->base, da->cur_size, prot));
@ -346,7 +342,7 @@ LibError da_read(DynArray* da, void* data, size_t size)
{
// make sure we have enough data to read
if(da->pos+size > da->cur_size)
return ERR_EOF;
WARN_RETURN(ERR_EOF);
memcpy2(data, da->base+da->pos, size);
da->pos += size;
@ -557,7 +553,7 @@ LibError bucket_create(Bucket* b, size_t el_size)
// cause next bucket_alloc to retry the allocation
b->pos = BUCKET_SIZE;
b->num_buckets = 0;
return ERR_NO_MEM;
WARN_RETURN(ERR_NO_MEM);
}
*(u8**)b->bucket = 0; // terminate list

View File

@ -344,7 +344,11 @@ private:
void init()
{
if(da_alloc(&da, sizeof(T)) < 0)
goto fail;
{
fail:
WARN_ERR(ERR_NO_MEM);
return;
}
if(da_set_size(&da, sizeof(T)) < 0)
goto fail;
@ -352,10 +356,6 @@ private:
cached_ptr = new(da.base) T();
#include "mmgr.h"
lock();
return; // success
fail:
debug_warn("OverrunProtector mem alloc failed");
}
void shutdown()

View File

@ -217,10 +217,7 @@ LibError debug_write_crashlog(const wchar_t* text)
strcat_s(N_path, ARRAY_SIZE(N_path), "crashlog.txt");
FILE* f = fopen(N_path, "w");
if(!f)
{
DISPLAY_ERROR(L"debug_write_crashlog: unable to open file");
return ERR_FILE_ACCESS;
}
WARN_RETURN(ERR_FILE_ACCESS);
fputwc(0xfeff, f); // BOM
fwprintf(f, L"%ls\n", text);
@ -260,7 +257,7 @@ static const char* symbol_string_build(void* symbol, const char* name, const cha
string_buf = (char*)malloc(STRING_BUF_SIZE);
if(!string_buf)
{
debug_warn("failed to allocate string_buf");
WARN_ERR(ERR_NO_MEM);
return 0;
}
string_buf_pos = string_buf;
@ -270,7 +267,7 @@ static const char* symbol_string_build(void* symbol, const char* name, const cha
char* string = string_buf_pos;
if(string + STRING_MAX >= string_buf + STRING_BUF_SIZE)
{
debug_warn("increase STRING_BUF_SIZE");
WARN_ERR(ERR_LIMIT);
return 0;
}
@ -393,10 +390,7 @@ static void symbol_string_add_to_cache(const char* string, void* symbol)
// hash table is completely full (guard against infinite loop below).
// if this happens, the string won't be cached - nothing serious.
if(total_symbols >= MAX_SYMBOLS)
{
debug_warn("increase MAX_SYMBOLS");
return;
}
WARN_ERR_RETURN(ERR_LIMIT);
total_symbols++;
// find Symbol slot in hash table

View File

@ -198,7 +198,7 @@ void get_snd_info()
// At least reset the values for unhandled platforms. Should perhaps do
// something like storing the OpenAL version or similar.
debug_assert(SND_CARD_LEN >= 8 && SND_DRV_VER_LEN >= 8); // protect strcpy
strcpy(snd_card, "Unknown"); // safe
strcpy(snd_drv_ver, "Unknown"); // safe
SAFE_STRCPY(snd_card, "Unknown");
SAFE_STRCPY(snd_drv_ver, "Unknown");
#endif
}

View File

@ -34,10 +34,7 @@ void in_add_handler(InHandler handler)
debug_assert(handler);
if(handler_stack_top >= MAX_HANDLERS)
{
debug_warn("increase MAX_HANDLERS");
return;
}
WARN_ERR_RETURN(ERR_LIMIT);
handler_stack[handler_stack_top++] = handler;
}
@ -103,7 +100,7 @@ LibError in_record(const char* fn)
f = fopen(fn, "wb");
if(!f)
return ERR_FILE_ACCESS;
WARN_RETURN(ERR_FILE_ACCESS);
fwrite(&game_ticks, sizeof(u32), 1, f);
@ -122,7 +119,7 @@ LibError in_playback(const char* fn)
f = fopen(fn, "rb");
if(!f)
return ERR_FILE_NOT_FOUND;
WARN_RETURN(ERR_FILE_NOT_FOUND);
u32 rec_start_time;
fread(&rec_start_time, sizeof(u32), 1, f);

View File

@ -49,36 +49,42 @@ void error_description_r(LibError err, char* buf, size_t max_chars)
}
// return the LibError equivalent of errno, or ERR_FAIL if
// there's no equal.
// return the LibError equivalent of errno, or ERR_FAIL if there's no equal.
// only call after a POSIX function indicates failure.
LibError LibError_from_errno()
// raises a warning (avoids having to on each call site).
LibError LibError_from_errno(bool warn_if_failed)
{
LibError err;
switch(errno)
{
case ENOMEM: return ERR_NO_MEM;
case ENOMEM: err = ERR_NO_MEM; break;
case EINVAL: return ERR_INVALID_PARAM;
case ENOSYS: return ERR_NOT_IMPLEMENTED;
case EINVAL: err = ERR_INVALID_PARAM; break;
case ENOSYS: err = ERR_NOT_IMPLEMENTED; break;
case ENOENT: return ERR_PATH_NOT_FOUND;
case EACCES: return ERR_FILE_ACCESS;
case EIO: return ERR_IO;
case ENAMETOOLONG: return ERR_PATH_LENGTH;
case ENOENT: err = ERR_PATH_NOT_FOUND; break;
case EACCES: err = ERR_FILE_ACCESS; break;
case EIO: err = ERR_IO; break;
case ENAMETOOLONG: err = ERR_PATH_LENGTH; break;
default: return ERR_FAIL;
default: err = ERR_FAIL; break;
}
UNREACHABLE;
if(warn_if_failed)
DEBUG_WARN_ERR(err);
return err;
}
// translate the return value of any POSIX function into LibError.
// ret is typically to -1 to indicate error and 0 on success.
// you should set errno to 0 before calling the POSIX function to
// make sure we do not return any stale errors.
LibError LibError_from_posix(int ret)
LibError LibError_from_posix(int ret, bool warn_if_failed)
{
debug_assert(ret == 0 || ret == -1);
return (ret == 0)? ERR_OK : LibError_from_errno();
if(ret == 0)
return ERR_OK;
return LibError_from_errno(warn_if_failed);
}

View File

@ -58,13 +58,14 @@ extern void error_description_r(LibError err, char* buf, size_t max_chars);
// return the LibError equivalent of errno, or ERR_FAIL if there's no equal.
// only call after a POSIX function indicates failure.
extern LibError LibError_from_errno();
// raises a warning (avoids having to on each call site).
extern LibError LibError_from_errno(bool warn_if_failed = true);
// translate the return value of any POSIX function into LibError.
// ret is typically to -1 to indicate error and 0 on success.
// you should set errno to 0 before calling the POSIX function to
// make sure we do not return any stale errors.
extern LibError LibError_from_posix(int ret);
extern LibError LibError_from_posix(int ret, bool warn_if_failed = true);
// set errno to the equivalent of <err>. used in wposix - underlying
// functions return LibError but must be translated to errno at
@ -264,30 +265,45 @@ ERR(-100221, ERR_INVALID_HANDLE, "Invalid Handle (argument)")
ERR(-100222, ERR_BUF_SIZE, "Buffer argument too small")
// system limitations
ERR(-100240, ERR_NO_MEM, "Not enough memory")
ERR(-100241, ERR_AGAIN, "Try again later")
ERR(-100242, ERR_LIMIT, "Fixed limit exceeded")
ERR(-100243, ERR_NO_SYS, "OS doesn't provide a required API")
ERR(-100244, ERR_NOT_IMPLEMENTED, "Feature currently not implemented")
ERR(-100245, ERR_NOT_SUPPORTED, "Feature isn't and won't be supported")
ERR(-100240, ERR_AGAIN, "Try again later")
ERR(-100241, ERR_LIMIT, "Fixed limit exceeded")
ERR(-100242, ERR_NO_SYS, "OS doesn't provide a required API")
ERR(-100243, ERR_NOT_IMPLEMENTED, "Feature currently not implemented")
ERR(-100244, ERR_NOT_SUPPORTED, "Feature isn't and won't be supported")
// memory
ERR(-100260, ERR_NO_MEM, "Not enough memory")
ERR(-100261, ERR_ALLOC_NOT_FOUND, "Not a valid allocated address")
// file + vfs
ERR(-100300, ERR_FILE_NOT_FOUND, "VFile not found")
ERR(-100301, ERR_PATH_NOT_FOUND, "VDir not found")
ERR(-100302, ERR_PATH_LENGTH, "Path exceeds VFS_MAX_PATH characters")
ERR(-100303, ERR_PATH_INVALID, "Path is invalid")
ERR(-100310, ERR_DIR_END, "End of directory reached (no more files)")
ERR(-100320, ERR_NOT_FILE, "Not a file")
// .. path
ERR(-100300, ERR_PATH_LENGTH, "Path exceeds VFS_MAX_PATH characters")
ERR(-100301, ERR_PATH_EMPTY, "Path is an empty string")
ERR(-100302, ERR_PATH_NOT_RELATIVE, "Path is not relative")
ERR(-100303, ERR_PATH_NON_PORTABLE, "Path contains OS-specific dir separator")
ERR(-100304, ERR_PATH_NON_CANONICAL, "Path contains unsupported .. or ./")
ERR(-100305, ERR_PATH_COMPONENT_SEPARATOR, "Path component contains dir separator")
// .. open
ERR(-100310, ERR_FILE_NOT_FOUND, "VFile not found")
ERR(-100311, ERR_NOT_FILE, "Not a file")
ERR(-100312, ERR_FILE_ACCESS, "Insufficient access rights to open file")
// .. enum
ERR(-100320, ERR_PATH_NOT_FOUND, "VDir not found")
ERR(-100321, ERR_NOT_DIR, "Not a directory")
ERR(-100330, ERR_FILE_ACCESS, "Insufficient access rights to open file")
ERR(-100331, ERR_IO, "Error during IO")
ERR(-100332, ERR_EOF, "Reading beyond end of file")
ERR(-100340, ERR_UNKNOWN_CMETHOD, "Unknown/unsupported compression method")
ERR(-100341, ERR_IS_COMPRESSED, "Invalid operation for a compressed file")
ERR(-100350, ERR_ALREADY_MOUNTED, "Directory (tree) already mounted")
ERR(-100351, ERR_INVALID_MOUNT_TYPE, "Invalid mount type (memory corruption?)")
ERR(-100360, ERR_NOT_IN_CACHE, "[Internal] Entry not found in cache")
ERR(-100370, ERR_TRACE_EMPTY, "No valid entries in trace")
ERR(-100322, ERR_DIR_END, "End of directory reached (no more files)")
// .. IO
ERR(-100330, ERR_IO, "Error during IO")
ERR(-100331, ERR_EOF, "Reading beyond end of file")
// .. mount
ERR(-100340, ERR_ALREADY_MOUNTED, "Directory (tree) already mounted")
ERR(-100341, ERR_INVALID_MOUNT_TYPE, "Invalid mount type (memory corruption?)")
ERR(-100342, ERR_ROOT_DIR_ALREADY_SET, "Attempting to set FS root dir more than once")
// .. misc
ERR(-100350, ERR_UNKNOWN_CMETHOD, "Unknown/unsupported compression method")
ERR(-100351, ERR_IS_COMPRESSED, "Invalid operation for a compressed file")
ERR(-100352, ERR_NOT_MAPPED, "File was not mapped")
ERR(-100353, ERR_NOT_IN_CACHE, "[Internal] Entry not found in cache")
ERR(-100354, ERR_TRACE_EMPTY, "No valid entries in trace")
// file format
ERR(-100400, ERR_UNKNOWN_FORMAT, "Unknown file format")
@ -306,6 +322,8 @@ ERR(-100507, ERR_TEX_CODEC_CANNOT_HANDLE, "Texture codec cannot handle the given
// CPU
ERR(-100600, ERR_CPU_FEATURE_MISSING, "This CPU doesn't support a required feature")
ERR(-100601, ERR_CPU_UNKNOWN_OPCODE, "Disassembly failed")
ERR(-100602, ERR_CPU_RESTRICTED_AFFINITY, "Cannot set desired CPU affinity")
// shaders
ERR(-100700, ERR_SHDR_CREATE, "Shader creation failed")
@ -337,5 +355,8 @@ ERR(-100900, ERR_STL_CNT_UNKNOWN, "Unknown STL container type_name")
// .. likely causes: not yet initialized or memory corruption.
ERR(-100901, ERR_STL_CNT_INVALID, "Container type is known but contents are invalid")
// timer
ERR(-101000, ERR_TIMER_NO_SAFE_IMPL, "No safe time source available")
#undef ERR
#endif // #ifdef ERR

View File

@ -341,7 +341,7 @@ LibError ogl_get_gfx_info()
// can fail if OpenGL not yet initialized,
// or if called between glBegin and glEnd.
if(!vendor || !renderer || !version)
return ERR_AGAIN;
WARN_RETURN(ERR_AGAIN);
snprintf(gfx_card, ARRAY_SIZE(gfx_card), "%s %s", vendor, renderer);

View File

@ -54,24 +54,28 @@ inf_*: in-memory inflate routines (zlib wrapper)
decompresses blocks from file_io callback.
*/
static LibError LibError_from_zlib(int err)
static LibError LibError_from_zlib(int zlib_err, bool warn_if_failed = true)
{
switch(err)
LibError err;
switch(zlib_err)
{
case Z_OK:
return ERR_OK;
case Z_STREAM_END:
return ERR_EOF;
err = ERR_EOF; break;
case Z_MEM_ERROR:
return ERR_NO_MEM;
err = ERR_NO_MEM; break;
case Z_DATA_ERROR:
return ERR_CORRUPTED;
err = ERR_CORRUPTED; break;
case Z_STREAM_ERROR:
return ERR_INVALID_PARAM;
err = ERR_INVALID_PARAM; break;
default:
return ERR_FAIL;
err = ERR_FAIL; break;
}
UNREACHABLE;
if(warn_if_failed)
DEBUG_WARN_ERR(err);
return err;
}
@ -176,7 +180,7 @@ public:
{
void* cdata_copy = malloc(buf.csize);
if(!cdata_copy)
return ERR_NO_MEM;
WARN_RETURN(ERR_NO_MEM);
memcpy2(cdata_copy, buf.cdata, buf.csize);
buf.cdata = (const u8*)cdata_copy;
}
@ -301,8 +305,7 @@ public:
const int windowBits = -MAX_WBITS; // max window size; omit ZLib header
ret = inflateInit2(&zs, windowBits);
}
CHECK_ERR(LibError_from_zlib(ret));
return ERR_OK;
return LibError_from_zlib(ret);
}
virtual LibError reset()
@ -313,8 +316,7 @@ public:
ret = deflateReset(&zs);
else
ret = inflateReset(&zs);
CHECK_ERR(LibError_from_zlib(ret));
return ERR_OK;
return LibError_from_zlib(ret);
}
@ -366,8 +368,7 @@ public:
next_out = zs.next_out;
avail_out = zs.avail_out;
CHECK_ERR(LibError_from_zlib(ret));
return ERR_OK;
return LibError_from_zlib(ret);
}
@ -403,7 +404,7 @@ public:
ret = deflateEnd(&zs);
else
ret = inflateEnd(&zs);
WARN_ERR(LibError_from_zlib(ret));
(void)LibError_from_zlib(ret, true); // just warn
}
};
@ -434,8 +435,8 @@ uintptr_t comp_alloc(ContextType type, CompressionMethod method)
break;
#endif
default:
debug_warn("unknown compression type");
compressor_allocator.release(c_mem);
WARN_ERR(ERR_UNKNOWN_CMETHOD);
return 0;
}

View File

@ -198,7 +198,7 @@ LibError ogl_shader_attach(GLhandleARB program, Handle& h)
H_DEREF(h, Ogl_Shader, shdr);
if (!shdr->id)
return ERR_SHDR_NO_SHADER;
WARN_RETURN(ERR_SHDR_NO_SHADER);
pglAttachObjectARB(program, shdr->id);

View File

@ -712,7 +712,7 @@ static LibError get_mipmaps(Tex* t, GLint filter, uint q_flags, int* plevels_to_
// all<->all transforms aren't implemented, it'd have to decompress
// from S3TC first), and DDS images ought to include mipmaps!
else if(is_s3tc)
return ERR_FAIL;
return ERR_FAIL; // NOWARN
// image is uncompressed and we're on an old OpenGL implementation;
// we will generate mipmaps in software.
else

View File

@ -223,7 +223,7 @@ TIMER_ACCRUE(tc_plain_transform);
Handle hm;
void* new_data = mem_alloc(data_size, 4*KiB, 0, &hm);
if(!new_data)
return ERR_NO_MEM;
WARN_RETURN(ERR_NO_MEM);
memcpy2(new_data, data, data_size);
// setup row source/destination pointers (simplifies outer loop)
@ -293,13 +293,13 @@ TIMER_ACCRUE(tc_plain_transform);
// go to the trouble of implementing image scaling because
// the only place this is used (ogl_tex_upload) requires POT anyway.
if(!is_pow2(w) || !is_pow2(h))
return ERR_TEX_INVALID_SIZE;
WARN_RETURN(ERR_TEX_INVALID_SIZE);
t->flags |= TEX_MIPMAPS; // must come before tex_img_size!
const size_t mipmap_size = tex_img_size(t);
Handle hm;
const u8* mipmap_data = (const u8*)mem_alloc(mipmap_size, 4*KiB, 0, &hm);
if(!mipmap_data)
return ERR_NO_MEM;
WARN_RETURN(ERR_NO_MEM);
CreateLevelData cld = { bpp/8, w, h, (const u8*)new_data, data_size };
tex_util_foreach_mipmap(w, h, bpp, mipmap_data, 0, 1, create_level, &cld);
mem_free_h(t->hm);
@ -449,10 +449,10 @@ static LibError tex_load_impl(FileIOBuf file_, size_t file_size, Tex* t)
// make sure the entire header has been read
const size_t min_hdr_size = c->hdr_size(0);
if(file_size < min_hdr_size)
return ERR_INCOMPLETE_HEADER;
WARN_RETURN(ERR_INCOMPLETE_HEADER);
const size_t hdr_size = c->hdr_size(file);
if(file_size < hdr_size)
return ERR_INCOMPLETE_HEADER;
WARN_RETURN(ERR_INCOMPLETE_HEADER);
t->ofs = hdr_size;
DynArray da;
@ -464,10 +464,12 @@ static LibError tex_load_impl(FileIOBuf file_, size_t file_size, Tex* t)
// sanity checks
if(!t->w || !t->h || t->bpp > 32)
return ERR_TEX_FMT_INVALID;
// TODO: need to compare against the new t->hm (file may be compressed, cannot use file_size)
//if(mem_size < t->ofs + tex_img_size(t))
// return ERR_TEX_INVALID_SIZE;
WARN_RETURN(ERR_TEX_FMT_INVALID);
// .. note: decode() may have decompressed the image; cannot use file_size.
size_t hm_size;
void* unused = mem_get_ptr(t->hm, &hm_size);
if(hm_size < t->ofs + tex_img_size(t))
WARN_RETURN(ERR_TEX_INVALID_SIZE);
flip_to_global_orientation(t);
@ -681,10 +683,7 @@ LibError tex_write(Tex* t, const char* fn)
CHECK_ERR(tex_codec_for_filename(fn, &c));
// encode into <da>
LibError err;
size_t rounded_size;
ssize_t bytes_written;
err = c->encode(t, &da);
LibError err = c->encode(t, &da);
if(err < 0)
{
debug_printf("%s (%s) failed: %d", __func__, c->name, err);
@ -693,10 +692,12 @@ LibError tex_write(Tex* t, const char* fn)
}
// write to disk
rounded_size = round_up(da.cur_size, FILE_BLOCK_SIZE);
{
const size_t rounded_size = round_up(da.cur_size, file_sector_size);
(void)da_set_size(&da, rounded_size);
bytes_written = vfs_store(fn, da.base, da.pos);
const ssize_t bytes_written = vfs_store(fn, da.base, da.pos);
debug_assert(bytes_written == (ssize_t)da.pos);
}
fail:
(void)da_free(&da);

View File

@ -90,7 +90,7 @@ static LibError bmp_decode(DynArray* restrict da, Tex* restrict t)
// sanity checks
if(compress != BI_RGB)
return ERR_TEX_COMPRESSED;
WARN_RETURN(ERR_TEX_COMPRESSED);
t->w = w;
t->h = h;

View File

@ -26,7 +26,10 @@ int tex_codec_register(TexCodecVTbl* c)
}
// find codec that recognizes the desired output file extension
// find codec that recognizes the desired output file extension,
// or return ERR_UNKNOWN_FORMAT if unknown.
// note: does not raise a warning because it is used by
// tex_is_known_extension.
LibError tex_codec_for_filename(const char* fn, const TexCodecVTbl** c)
{
const char* ext = strrchr(fn, '.');
@ -50,7 +53,7 @@ LibError tex_codec_for_header(const u8* file, size_t file_size, const TexCodecVT
{
// we guarantee at least 4 bytes for is_hdr to look at
if(file_size < 4)
return ERR_INCOMPLETE_HEADER;
WARN_RETURN(ERR_INCOMPLETE_HEADER);
for(*c = codecs; *c; *c = (*c)->next)
{
@ -59,7 +62,7 @@ LibError tex_codec_for_header(const u8* file, size_t file_size, const TexCodecVT
return ERR_OK;
}
return ERR_UNKNOWN_FORMAT;
WARN_RETURN(ERR_UNKNOWN_FORMAT);
}
@ -106,7 +109,7 @@ LibError tex_codec_alloc_rows(const u8* data, size_t h, size_t pitch,
rows = (RowArray)malloc(h * sizeof(RowPtr));
if(!rows)
return ERR_NO_MEM;
WARN_RETURN(ERR_NO_MEM);
// determine start position and direction
RowPtr pos = flip? data+pitch*(h-1) : data;

View File

@ -59,7 +59,10 @@ struct TexCodecVTbl
extern int tex_codec_register(TexCodecVTbl* c);
// find codec that recognizes the desired output file extension
// find codec that recognizes the desired output file extension,
// or return ERR_UNKNOWN_FORMAT if unknown.
// note: does not raise a warning because it is used by
// tex_is_known_extension.
extern LibError tex_codec_for_filename(const char* fn, const TexCodecVTbl** c);
// find codec that recognizes the header's magic field

View File

@ -267,7 +267,7 @@ static LibError s3tc_decompress(Tex* t)
const size_t out_size = tex_img_size(t) * out_bpp / t->bpp;
void* out_data = mem_alloc(out_size, 64*KiB, 0, &hm);
if(!out_data)
return ERR_NO_MEM;
WARN_RETURN(ERR_NO_MEM);
const uint s3tc_block_size = (dxt == 3 || dxt == 5)? 16 : 8;
S3tcDecompressInfo di = { dxt, s3tc_block_size, out_bpp/8, (u8*)out_data };
@ -395,7 +395,7 @@ static LibError decode_pf(const DDPIXELFORMAT* pf, uint* bpp_, uint* flags_)
// check struct size
if(read_le32(&pf->dwSize) != sizeof(DDPIXELFORMAT))
return ERR_TEX_INVALID_SIZE;
WARN_RETURN(ERR_TEX_INVALID_SIZE);
// determine type
const u32 pf_flags = read_le32(&pf->dwFlags);
@ -462,12 +462,12 @@ static LibError decode_pf(const DDPIXELFORMAT* pf, uint* bpp_, uint* flags_)
break;
default:
return ERR_TEX_FMT_INVALID;
WARN_RETURN(ERR_TEX_FMT_INVALID);
}
}
// .. neither uncompressed nor compressed - invalid
else
return ERR_TEX_FMT_INVALID;
WARN_RETURN(ERR_TEX_FMT_INVALID);
*bpp_ = bpp;
*flags_ = flags;
@ -484,7 +484,7 @@ static LibError decode_sd(const DDSURFACEDESC2* sd, uint* w_, uint* h_,
{
// check header size
if(read_le32(&sd->dwSize) != sizeof(*sd))
return ERR_CORRUPTED;
WARN_RETURN(ERR_CORRUPTED);
// flags (indicate which fields are valid)
const u32 sd_flags = read_le32(&sd->dwFlags);
@ -492,14 +492,14 @@ static LibError decode_sd(const DDSURFACEDESC2* sd, uint* w_, uint* h_,
// note: we can't guess dimensions - the image may not be square.
const u32 sd_req_flags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT;
if((sd_flags & sd_req_flags) != sd_req_flags)
return ERR_INCOMPLETE_HEADER;
WARN_RETURN(ERR_INCOMPLETE_HEADER);
// image dimensions
const u32 h = read_le32(&sd->dwHeight);
const u32 w = read_le32(&sd->dwWidth);
// .. not padded to S3TC block size
if(w % 4 || h % 4)
return ERR_TEX_INVALID_SIZE;
WARN_RETURN(ERR_TEX_INVALID_SIZE);
// pixel format
uint bpp, flags;
@ -511,12 +511,12 @@ static LibError decode_sd(const DDSURFACEDESC2* sd, uint* w_, uint* h_,
if(sd_flags & DDSD_PITCH)
{
if(sd_pitch_or_size != round_up(pitch, 4))
return ERR_CORRUPTED;
WARN_RETURN(ERR_CORRUPTED);
}
if(sd_flags & DDSD_LINEARSIZE)
{
if(sd_pitch_or_size != pitch*h)
return ERR_CORRUPTED;
WARN_RETURN(ERR_CORRUPTED);
}
// note: both flags set would be invalid; no need to check for that,
// though, since one of the above tests would fail.
@ -530,7 +530,7 @@ static LibError decode_sd(const DDSURFACEDESC2* sd, uint* w_, uint* h_,
// mipmap chain is incomplete
// note: DDS includes the base level in its count, hence +1.
if(mipmap_count != log2(MAX(w,h))+1)
return ERR_TEX_FMT_INVALID;
WARN_RETURN(ERR_TEX_FMT_INVALID);
flags |= TEX_MIPMAPS;
}
}
@ -540,7 +540,7 @@ static LibError decode_sd(const DDSURFACEDESC2* sd, uint* w_, uint* h_,
{
const u32 depth = read_le32(&sd->dwDepth);
if(depth)
return ERR_NOT_IMPLEMENTED;
WARN_RETURN(ERR_NOT_IMPLEMENTED);
}
// check caps

View File

@ -456,7 +456,7 @@ static LibError jpg_decode_impl(DynArray* da,
const size_t img_size = pitch * h; // for allow_rows
u8* img = (u8*)mem_alloc(img_size, 64*KiB, 0, &img_hm);
if(!img)
return ERR_NO_MEM;
WARN_RETURN(ERR_NO_MEM);
// read rows
RETURN_ERR(tex_codec_alloc_rows(img, h, pitch, TEX_TOP_DOWN, 0, rows));

View File

@ -97,14 +97,14 @@ static LibError png_decode_impl(DynArray* da,
// make sure format is acceptable
if(bit_depth != 8)
return ERR_TEX_NOT_8BIT_PRECISION;
WARN_RETURN(ERR_TEX_NOT_8BIT_PRECISION);
if(colour_type & PNG_COLOR_MASK_PALETTE)
return ERR_TEX_INVALID_COLOR_TYPE;
WARN_RETURN(ERR_TEX_INVALID_COLOR_TYPE);
const size_t img_size = pitch * h;
u8* img = (u8*)mem_alloc(img_size, 64*KiB, 0, &img_hm);
if(!img)
return ERR_NO_MEM;
WARN_RETURN(ERR_NO_MEM);
RETURN_ERR(tex_codec_alloc_rows(img, h, pitch, TEX_TOP_DOWN, 0, rows));

View File

@ -110,7 +110,7 @@ static LibError tga_decode(DynArray* restrict da, Tex* restrict t)
// .. storing right-to-left is just stupid;
// we're not going to bother converting it.
if(desc & TGA_RIGHT_TO_LEFT)
return ERR_TEX_INVALID_LAYOUT;
WARN_RETURN(ERR_TEX_INVALID_LAYOUT);
t->w = w;
t->h = h;

View File

@ -83,10 +83,7 @@ static LibError UniFont_reload(UniFont* f, const char* fn, Handle UNUSED(h))
int Version;
FNTStream >> Version;
if (Version != 100) // Make sure this is from a recent version of the font builder
{
debug_warn("Invalid .fnt version number");
return ERR_UNKNOWN_FORMAT;
}
WARN_RETURN(ERR_UNKNOWN_FORMAT);
int TextureWidth, TextureHeight;
FNTStream >> TextureWidth >> TextureHeight;
@ -103,10 +100,7 @@ static LibError UniFont_reload(UniFont* f, const char* fn, Handle UNUSED(h))
f->ListBase = glGenLists(NumGlyphs);
if (f->ListBase == 0) // My Voodoo2 drivers didn't support display lists (although I'd be surprised if they got this far)
{
debug_warn("Display list creation failed");
return ERR_FAIL;
}
WARN_RETURN(ERR_FAIL);
for (int i = 0; i < NumGlyphs; ++i)
{

View File

@ -283,15 +283,13 @@ static LibError alloc_idx(i32& idx, HDATA*& hd)
}
// add another
// .. too many already: IDX_BITS must be increased.
if(last_in_use >= hdata_cap)
{
debug_warn("too many open handles (increase IDX_BITS)");
return ERR_LIMIT;
}
WARN_RETURN(ERR_LIMIT);
idx = last_in_use+1; // just incrementing idx would start it at 1
hd = h_data_from_idx(idx);
if(!hd)
return ERR_NO_MEM;
WARN_RETURN(ERR_NO_MEM);
// can't fail for any other reason - idx is checked above.
{ // VC6 goto fix
bool is_unused = !hd->tag;
@ -439,10 +437,7 @@ static void fn_store(HDATA* hd, const char* fn)
hd->fn = (const char*)malloc(size);
// still failed - bail (avoid strcpy to 0)
if(!hd->fn)
{
debug_warn("not enough memory to store hd->fn!");
return;
}
WARN_ERR_RETURN(ERR_NO_MEM);
}
memcpy2((void*)hd->fn, fn, size); // faster than strcpy
@ -510,20 +505,11 @@ static void warn_if_invalid(HDATA* hd)
static LibError type_validate(H_Type type)
{
if(!type)
{
debug_warn("type is 0");
return ERR_INVALID_PARAM;
}
if(type->user_size > HDATA_USER_SIZE)
{
debug_warn("type's user data is too large for HDATA");
return ERR_LIMIT;
}
if(type->name == 0)
{
debug_warn("type's name field is 0");
return ERR_INVALID_PARAM;
}
return ERR_OK;
}
@ -553,11 +539,9 @@ static Handle reuse_existing_handle(uintptr_t key, H_Type type, uint flags)
return 0;
HDATA* hd = h_data_tag_type(h, type);
// too many references - increase REF_BITS
if(hd->refs == REF_MAX)
{
debug_warn("too many references to a handle - increase REF_BITS");
return ERR_LIMIT;
}
WARN_RETURN(ERR_LIMIT);
hd->refs++;
@ -812,13 +796,10 @@ const char* h_filename(const Handle h)
// TODO: what if iterating through all handles is too slow?
LibError h_reload(const char* fn)
{
// must not continue - some resources not backed by files have
// key = 0 and reloading those would be disastrous.
if(!fn)
{
debug_warn("fn = 0");
// must not continue - some resources not backed by files have
// key = 0 and reloading those would be disastrous.
return ERR_INVALID_PARAM;
}
WARN_RETURN(ERR_INVALID_PARAM);
const u32 key = fnv_hash(fn);
@ -879,7 +860,7 @@ LibError h_force_free(Handle h, H_Type type)
// require valid index; ignore tag; type checked below.
HDATA* hd = h_data_no_tag(h);
if(!hd || hd->type != type)
return ERR_INVALID_HANDLE;
WARN_RETURN(ERR_INVALID_HANDLE);
u32 idx = h_idx(h);
hd->keep_open = 0;
hd->refs = 0;
@ -920,10 +901,7 @@ int h_get_refcnt(Handle h)
{
HDATA* hd = h_data_tag(h);
if(!hd)
{
debug_warn("invalid handle");
return ERR_INVALID_PARAM;
}
WARN_RETURN(ERR_INVALID_PARAM);
// if there are no refs, how did the caller manage to keep a Handle?!
if(!hd->refs)

View File

@ -53,7 +53,7 @@ static Handle find_alloc(void* target_raw_p, It* out_it = 0)
{
Ptr2H* ptr2h = ptr2h_wrapper.get();
if(!ptr2h)
return ERR_NO_MEM;
WARN_RETURN(ERR_NO_MEM);
// early out optimization (don't pay for full subset check)
It it = ptr2h->find(target_raw_p);
@ -242,10 +242,7 @@ LibError mem_free_p(void*& p)
p = 0;
if(hm <= 0)
{
debug_warn("mem_free_p: not found in map");
return ERR_FAIL;
}
WARN_RETURN(ERR_ALLOC_NOT_FOUND);
return mem_free_h(hm);
}

View File

@ -48,6 +48,7 @@
#include "../res.h"
#include "snd.h"
#include "lib/timer.h"
#include "app_hooks.h"
@ -249,6 +250,13 @@ static LibError alc_init()
ret = ERR_FAIL;
}
// make note of which sound device is actually being used
// (e.g. DS3D, native, MMSYSTEM) - needed when reporting OpenAL bugs.
const char* dev_name = (const char*)alcGetString(alc_dev, ALC_DEVICE_SPECIFIER);
wchar_t buf[200];
swprintf(buf, ARRAY_SIZE(buf), L"SND| alc_init: success, using %hs\n", dev_name);
ah_log(buf);
// release DLL references, so BoundsChecker doesn't complain at exit.
#if OS_WIN
for(int i = 0; i < ARRAY_SIZE(dlls); i++)
@ -294,10 +302,7 @@ static void al_listener_latch()
LibError snd_set_master_gain(float gain)
{
if(gain < 0)
{
debug_warn("gain < 0");
return ERR_INVALID_PARAM;
}
WARN_RETURN(ERR_INVALID_PARAM);
al_listener_gain = gain;
@ -572,7 +577,7 @@ static const char* devs;
LibError snd_dev_prepare_enum()
{
if(alcIsExtensionPresent(0, (ALubyte*)"ALC_ENUMERATION_EXT") != AL_TRUE)
return ERR_NO_SYS;
WARN_RETURN(ERR_NO_SYS);
devs = (const char*)alcGetString(0, ALC_DEVICE_SPECIFIER);
return ERR_OK;
@ -660,11 +665,14 @@ static void* io_buf_alloc()
// note: we have to bail now; can't update io_buf_freelist.
if(!buf)
{
// no buffer allocated
if(!io_bufs)
debug_warn("not enough memory to allocate buffer pool");
WARN_ERR(ERR_NO_MEM);
// too many streams - can't happen (tm) because
// stream_open enforces MAX_STREAMS.
else
debug_warn("max #streams exceeded");
// can't happen (tm) because stream_open enforces MAX_STREAMS.
WARN_ERR(ERR_LIMIT);
return 0;
}
@ -707,7 +715,7 @@ static LibError stream_issue(Stream* s)
void* buf = io_buf_alloc();
if(!buf)
return ERR_NO_MEM;
WARN_RETURN(ERR_NO_MEM);
Handle h = vfs_io_issue(s->hf, STREAM_BUF_SIZE, buf);
CHECK_ERR(h);
@ -722,14 +730,14 @@ static LibError stream_issue(Stream* s)
static LibError stream_buf_get(Stream* s, void*& data, size_t& size)
{
if(s->active_ios == 0)
return ERR_EOF;
WARN_RETURN(ERR_EOF);
Handle hio = s->ios[0];
// has it finished? if not, bail.
int is_complete = vfs_io_has_completed(hio);
RETURN_ERR(is_complete);
if(is_complete == 0)
return ERR_AGAIN;
return ERR_AGAIN; // NOWARN
// get its buffer.
RETURN_ERR(vfs_io_wait(hio, data, size));
@ -770,12 +778,9 @@ static uint active_streams;
// open a stream and begin reading from disk.
static LibError stream_open(Stream* s, const char* fn)
{
// bail because we wouldn't have enough IO buffers for all
if(active_streams >= MAX_STREAMS)
{
debug_warn("MAX_STREAMS exceeded - why?");
// bail because we wouldn't have enough IO buffers for all
return ERR_LIMIT;
}
WARN_RETURN(ERR_LIMIT);
active_streams++;
s->hf = vfs_open(fn);
@ -927,7 +932,7 @@ static LibError SndData_reload(SndData* sd, const char* fn, Handle hsd)
if(ogg_supported == -1)
ogg_supported = alIsExtensionPresent((ALubyte*)"AL_EXT_vorbis")? 1 : 0;
if(!ogg_supported)
return ERR_NO_SYS;
WARN_RETURN(ERR_NO_SYS);
sd->al_fmt = AL_FORMAT_VORBIS_EXT;
sd->al_freq = 0;
@ -940,7 +945,7 @@ static LibError SndData_reload(SndData* sd, const char* fn, Handle hsd)
file_type = FT_WAV;
// .. unknown extension
else
return ERR_UNKNOWN_FORMAT;
WARN_RETURN(ERR_UNKNOWN_FORMAT);
if(sd->is_stream)
@ -948,7 +953,7 @@ static LibError SndData_reload(SndData* sd, const char* fn, Handle hsd)
// refuse to stream anything that cannot be passed directly to OpenAL -
// we'd have to extract the audio data ourselves (not worth it).
if(file_type != FT_OGG)
return ERR_NOT_SUPPORTED;
WARN_RETURN(ERR_NOT_SUPPORTED);
RETURN_ERR(stream_open(&sd->s, fn));
sd->is_valid = 1;
@ -1123,7 +1128,7 @@ static LibError snd_data_buf_get(Handle hsd, ALuint& al_buf)
if(!sd->is_stream)
{
al_buf = sd->al_buf;
return ERR_EOF;
return ERR_EOF; // NOWARN
}
// stream:
@ -1133,7 +1138,7 @@ static LibError snd_data_buf_get(Handle hsd, ALuint& al_buf)
size_t size;
err = stream_buf_get(&sd->s, data, size);
if(err == ERR_AGAIN)
return ERR_AGAIN;
return ERR_AGAIN; // NOWARN
CHECK_ERR(err);
// .. yes: pass to OpenAL and discard IO buffer.
@ -1144,7 +1149,7 @@ static LibError snd_data_buf_get(Handle hsd, ALuint& al_buf)
// if EOF reached, indicate al_buf is the last that will be returned.
err = stream_issue(&sd->s);
if(err == ERR_EOF)
return ERR_EOF;
return ERR_EOF; // NOWARN
CHECK_ERR(err);
// al_buf valid and next IO issued successfully.
@ -1681,7 +1686,7 @@ static LibError vsrc_grant(VSrc* vs)
// we get called in that hope that one is available by snd_play.
vs->al_src = al_src_alloc();
if(!vs->al_src)
return ERR_FAIL;
return ERR_FAIL; // NOWARN
// OpenAL docs don't specify default values, so initialize everything
// ourselves to be sure. note: alSourcefv param is not const.
@ -1711,7 +1716,7 @@ static LibError vsrc_reclaim(VSrc* vs)
{
// don't own a source - bail.
if(!vs->al_src)
return ERR_FAIL;
return ERR_FAIL; // NOWARN
alSourceStop(vs->al_src);
al_check("src_stop");
@ -2006,7 +2011,7 @@ static inline LibError snd_init()
{
// (note: each VSrc_reload and therefore snd_open will fail)
if(snd_disabled)
return ERR_AGAIN;
return ERR_AGAIN; // NOWARN
return al_init();
}

View File

@ -645,7 +645,7 @@ LibError ia32_get_call_target(void* ret_addr, void** target)
if(len >= 2 && c[-2] == 0xFF && (c[-1] & 0xF8) == 0xD0)
return ERR_OK;
return ERR_FAIL;
return ERR_CPU_UNKNOWN_OPCODE;
}

View File

@ -254,6 +254,28 @@ extern i64 i64_from_double(double);
#endif
// return the largest sector size [bytes] of any storage medium
// (HD, optical, etc.) in the system.
//
// this may be a bit slow to determine (iterates over all drives),
// but caches the result so subsequent calls are free.
// (caveat: device changes won't be noticed during this program run)
//
// sector size is relevant because Windows aio requires all IO
// buffers, offsets and lengths to be a multiple of it. this requirement
// is also carried over into the vfs / file.cpp interfaces for efficiency
// (avoids the need for copying to/from align buffers).
//
// waio uses the sector size to (in some cases) align IOs if
// they aren't already, but it's also needed by user code when
// aligning their buffers to meet the requirements.
//
// the largest size is used so that we can read from any drive. while this
// is a bit wasteful (more padding) and requires iterating over all drives,
// it is the only safe way: this may be called before we know which
// drives will be needed, and hardlinks may confuse things.
extern size_t sys_max_sector_size();
#if OS_WIN
#define DIR_SEP '\\'
#else

View File

@ -9,16 +9,17 @@
#include <fam.h>
static FAMConnection fc;
static bool initialized=false;
static bool initialized = false;
static std::map<intptr_t, std::string> dirs;
void fam_deinit()
// for atexit
static void fam_deinit()
{
FAMClose(&fc);
}
int dir_add_watch(const char* const n_full_path, intptr_t* const watch)
LibError dir_add_watch(const char* const n_full_path, intptr_t* const watch)
{
if(!initialized)
{
@ -32,22 +33,19 @@ int dir_add_watch(const char* const n_full_path, intptr_t* const watch)
{
*watch = -1;
debug_warn("res_watch_dir failed!");
return -1; // no way of getting error code?
return ERR_FAIL; // no way of getting error code?
}
*watch = (intptr_t)req.reqnum;
dirs[*watch] = n_full_path;
return 0;
return ERR_OK;
}
int dir_cancel_watch(const intptr_t watch)
LibError dir_cancel_watch(const intptr_t watch)
{
if(!initialized)
{
debug_warn("dir_cancel_watch before dir_add_watch");
return -1;
}
WARN_RETURN(ERR_LOGIC);
FAMRequest req;
req.reqnum = (int)watch;
@ -57,10 +55,11 @@ int dir_cancel_watch(const intptr_t watch)
int dir_get_changed_file(char* fn)
{
if(!initialized)
return ERR_FAIL;
WARN_RETURN(ERR_LOGIC);
FAMEvent e;
while(FAMPending(&fc) > 0)
{
if(FAMNextEvent(&fc, &e) >= 0)
{
if (e.code == FAMChanged || e.code == FAMCreated || e.code == FAMDeleted)
@ -72,6 +71,7 @@ int dir_get_changed_file(char* fn)
return ERR_OK;
}
}
}
return ERR_AGAIN;
return ERR_AGAIN; // NOWARN
}

View File

@ -37,18 +37,39 @@ WIN_REGISTER_FUNC(waio_init);
WIN_REGISTER_FUNC(waio_shutdown);
#pragma data_seg()
// Win32 functions require sector aligned transfers.
// max of all drives' size is checked in waio_init().
static size_t sector_size = 512; // minimum: one page
static void determine_max_sector_size()
// return the largest sector size [bytes] of any storage medium
// (HD, optical, etc.) in the system.
//
// this may be a bit slow to determine (iterates over all drives),
// but caches the result so subsequent calls are free.
// (caveat: device changes won't be noticed during this program run)
//
// sector size is relevant because Windows aio requires all IO
// buffers, offsets and lengths to be a multiple of it. this requirement
// is also carried over into the vfs / file.cpp interfaces for efficiency
// (avoids the need for copying to/from align buffers).
//
// waio uses the sector size to (in some cases) align IOs if
// they aren't already, but it's also needed by user code when
// aligning their buffers to meet the requirements.
//
// the largest size is used so that we can read from any drive. while this
// is a bit wasteful (more padding) and requires iterating over all drives,
// it is the only safe way: this may be called before we know which
// drives will be needed, and hardlinks may confuse things.
size_t sys_max_sector_size()
{
// currently disabled: DVDs have 2..4KB, but this causes
// waio to unnecessarily align some file transfers (when at EOF)
// this means that we might not be able to read from CD/DVD drives
// (ReadFile will return error)
/*
// users may call us more than once, so cache the results.
static size_t cached_sector_size;
if(cached_sector_size)
return cached_sector_size;
// currently disabled: DVDs have 2..4KB, but this causes
// waio to unnecessarily align some file transfers (when at EOF)
// this means that we might not be able to read from CD/DVD drives
// (ReadFile will return error)
// reactivated for correctness.
// temporarily disable the "insert disk into drive" error box; we are
// only interested in fixed drives anyway.
//
@ -57,9 +78,7 @@ static void determine_max_sector_size()
const UINT old_err_mode = SetErrorMode(0);
SetErrorMode(old_err_mode|SEM_FAILCRITICALERRORS);
// Win32 requires transfers to be sector aligned.
// find maximum of all drive's sector sizes, then use that.
// (it's good to know this up-front, and checking every open() is slow).
// find maximum of all drive's sector sizes.
const DWORD drives = GetLogicalDrives();
char drive_str[4] = "?:\\";
for(int drive = 2; drive <= 26; drive++) // C: .. Z:
@ -71,12 +90,9 @@ static void determine_max_sector_size()
drive_str[0] = (char)('A'+drive);
DWORD spc, nfc, tnc; // don't need these
DWORD sector_size2;
if(GetDiskFreeSpace(drive_str, &spc, &sector_size2, &nfc, &tnc))
{
if(sector_size < sector_size2)
sector_size = sector_size2;
}
DWORD cur_sector_size;
if(GetDiskFreeSpace(drive_str, &spc, &cur_sector_size, &nfc, &tnc))
cached_sector_size = MAX(cached_sector_size, cur_sector_size);
// otherwise, it's probably an empty CD drive. ignore the
// BoundsChecker error; GetDiskFreeSpace seems to be the
// only way of getting at the sector size.
@ -84,8 +100,10 @@ static void determine_max_sector_size()
SetErrorMode(old_err_mode);
debug_assert(is_pow2((long)sector_size));
*/
// sanity check; believed to be the case for all drives.
debug_assert(cached_sector_size % 512 == 0);
return cached_sector_size;
}
@ -186,10 +204,12 @@ static HANDLE aio_h_get(const int fd)
// setting h = INVALID_HANDLE_VALUE removes the association.
static LibError aio_h_set(const int fd, const HANDLE h)
{
if(fd < 0)
WARN_RETURN(ERR_INVALID_PARAM);
lock();
if(fd < 0)
goto fail;
LibError err;
// grow hs array to at least fd+1 entries
if(fd >= aio_hs_size)
@ -197,7 +217,10 @@ static LibError aio_h_set(const int fd, const HANDLE h)
const uint size2 = (uint)round_up(fd+8, 8);
HANDLE* hs2 = (HANDLE*)realloc(aio_hs, size2*sizeof(HANDLE));
if(!hs2)
{
err = ERR_NO_MEM;
goto fail;
}
// don't assign directly from realloc -
// we'd leak the previous array if realloc fails.
@ -207,17 +230,25 @@ static LibError aio_h_set(const int fd, const HANDLE h)
aio_hs_size = size2;
}
// nothing to do; will set aio_hs[fd] to INVALID_HANDLE_VALUE below.
if(h == INVALID_HANDLE_VALUE)
;
{
// nothing to do; will set aio_hs[fd] to INVALID_HANDLE_VALUE below.
}
else
{
// already set
if(aio_hs[fd] != INVALID_HANDLE_VALUE)
{
err = ERR_LOGIC;
goto fail;
}
// setting invalid handle
if(!is_valid_file_handle(h))
{
err = ERR_NOT_FILE;
goto fail;
}
}
aio_hs[fd] = h;
@ -227,8 +258,7 @@ static LibError aio_h_set(const int fd, const HANDLE h)
fail:
unlock();
debug_warn("failed");
return ERR_FAIL;
WARN_RETURN(err);
}
@ -466,13 +496,18 @@ static int aio_rw(struct aiocb* cb)
// align
//
// actual transfer parameters
// (possibly rounded up/down to satisfy Win32 alignment requirements)
// Win32 requires transfers to be sector aligned.
// we check if the transfer is aligned to sector size (the max of
// all drives in the system) and copy to/from align buffer if not.
// actual transfer parameters (possibly rounded up/down)
size_t actual_ofs = 0;
// assume socket; if file, set below
size_t actual_size = size;
void* actual_buf = buf;
const size_t sector_size = sys_max_sector_size();
// leave offset 0 if h is a socket (don't support seeking);
// otherwise, calculate aligned offset/size
const bool is_file = (GetFileType(h) == FILE_TYPE_DISK);
@ -515,7 +550,7 @@ static int aio_rw(struct aiocb* cb)
}
else
{
// unaligned offset: not supported.
// unaligned write offset: not supported.
// (we'd have to read padding, then write our data. ugh.)
if(ofs_misaligned)
{
@ -527,9 +562,9 @@ static int aio_rw(struct aiocb* cb)
if(buf_misaligned)
{
memcpy2(r->buf, buf, size);
memset((char*)r->buf + size, 0, actual_size - size);
// clear previous contents at end of align buf
actual_buf = r->buf;
// clear previous contents at end of align buf
memset((char*)r->buf + size, 0, actual_size - size);
}
// unaligned size: already taken care of (we round up)
@ -540,10 +575,9 @@ static int aio_rw(struct aiocb* cb)
// set OVERLAPPED fields
// note: Read-/WriteFile reset ovl.hEvent - no need to do that.
r->ovl.Internal = r->ovl.InternalHigh = 0;
*(size_t*)&r->ovl.Offset = actual_ofs;
// HACK: use this instead of OVERLAPPED.Pointer,
// which isn't defined in older headers (e.g. VC6).
// 64-bit clean, but endian dependent!
// note: OVERLAPPED.Pointer is more convenient but not defined on VC6.
r->ovl.Offset = u64_lo(actual_ofs);
r->ovl.OffsetHigh = u64_hi(actual_ofs);
DWORD size32 = (DWORD)(actual_size & 0xffffffff);
BOOL ok;
@ -760,7 +794,6 @@ int aio_fsync(int, struct aiocb*)
static LibError waio_init()
{
req_init();
determine_max_sector_size();
return ERR_OK;
}

View File

@ -260,10 +260,7 @@ LibError prof_start()
const DWORD access = THREAD_GET_CONTEXT|THREAD_SUSPEND_RESUME;
HANDLE hThread = OpenThread(access, FALSE, GetCurrentThreadId());
if(hThread == INVALID_HANDLE_VALUE)
{
debug_warn("OpenThread failed");
return ERR_FAIL;
}
WARN_RETURN(ERR_FAIL);
prof_target_thread = hThread;

View File

@ -204,10 +204,7 @@ static LibError call_while_suspended(WhileSuspendedFunc func, void* user_arg)
const DWORD access = THREAD_GET_CONTEXT|THREAD_SET_CONTEXT|THREAD_SUSPEND_RESUME;
HANDLE hThread = OpenThread(access, FALSE, GetCurrentThreadId());
if(hThread == INVALID_HANDLE_VALUE)
{
debug_warn("OpenThread failed");
return ERR_FAIL;
}
WARN_RETURN(ERR_FAIL);
WhileSuspendedParam param = { hThread, func, user_arg };
@ -281,8 +278,7 @@ static LibError brk_enable_in_ctx(BreakInfo* bi, CONTEXT* context)
if((context->Dr7 & LE) == 0)
goto have_reg;
}
debug_warn("brk_enable_in_ctx: no register available");
return ERR_LIMIT;
WARN_RETURN(ERR_LIMIT);
have_reg:
// store breakpoint address in debug register.
@ -352,10 +348,7 @@ static LibError brk_do_request(HANDLE hThread, void* arg)
CONTEXT context;
context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
if(!GetThreadContext(hThread, &context))
{
debug_warn("brk_do_request: GetThreadContext failed");
goto fail;
}
WARN_RETURN(ERR_FAIL);
#if CPU_IA32
if(bi->want_all_disabled)
@ -367,14 +360,10 @@ static LibError brk_do_request(HANDLE hThread, void* arg)
#endif
if(!SetThreadContext(hThread, &context))
{
debug_warn("brk_do_request: SetThreadContext failed");
goto fail;
}
WARN_RETURN(ERR_FAIL);
return ret;
fail:
return ERR_FAIL;
RETURN_ERR(ret);
return ERR_OK;
}

View File

@ -414,13 +414,15 @@ static LibError walk_stack(StackFrameCallback cb, void* user_arg = 0, uint skip
const HANDLE hThread = GetCurrentThread();
BOOL ok = StackWalk64(machine, hProcess, hThread, &sf, (PVOID)pcontext,
0, SymFunctionTableAccess64, SymGetModuleBase64, 0);
err = LibError_from_win32(ok);
// note: don't use LibError_from_win32 because it raises a warning,
// and this "fails" commonly (when no stack frames are left).
err = ok? ERR_OK : ERR_FAIL;
#endif
// no more frames found - abort. note: also test FP because
// StackWalk64 sometimes erroneously reports success.
void* fp = (void*)(uintptr_t)sf.AddrFrame .Offset;
if(err < 0 || !fp)
if(err != ERR_OK || !fp)
return ret;
if(skip)
@ -607,11 +609,11 @@ static void out_latch_pos()
static LibError out_check_limit()
{
if(out_have_warned_of_limit)
return ERR_SYM_SUPPRESS_OUTPUT;
return ERR_SYM_SUPPRESS_OUTPUT; // NOWARN
if(out_pos - out_latched_pos > 3000) // ~30 lines
{
out_have_warned_of_limit = true;
return ERR_SYM_SINGLE_SYMBOL_LIMIT;
return ERR_SYM_SINGLE_SYMBOL_LIMIT; // NOWARN
}
// no limit hit, proceed normally
@ -892,7 +894,7 @@ static LibError determine_symbol_address(DWORD id, DWORD UNUSED(type_id), const
DWORD data_kind;
if(!SymGetTypeInfo(hProcess, mod_base, id, TI_GET_DATAKIND, &data_kind))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
switch(data_kind)
{
// SymFromIndex will fail
@ -905,7 +907,7 @@ static LibError determine_symbol_address(DWORD id, DWORD UNUSED(type_id), const
// this symbol is defined as static in another module =>
// there's nothing we can do.
case DataIsStaticMember:
return ERR_SYM_UNRETRIEVABLE_STATIC;
return ERR_SYM_UNRETRIEVABLE_STATIC; // NOWARN
// ok; will handle below
case DataIsLocal:
@ -927,7 +929,7 @@ static LibError determine_symbol_address(DWORD id, DWORD UNUSED(type_id), const
SYMBOL_INFO_PACKAGEW2 sp;
SYMBOL_INFOW* sym = &sp.si;
if(!SymFromIndexW(hProcess, mod_base, id, sym))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
DWORD addrofs = 0;
ULONG64 addr2 = 0;
@ -968,7 +970,7 @@ fp_rel:
{
in_register:
*pp = (const u8*)(uintptr_t)sym->Register;
return ERR_SYM_UNRETRIEVABLE_REG;
return ERR_SYM_UNRETRIEVABLE_REG; // NOWARN
}
*pp = (const u8*)addr;
@ -992,18 +994,18 @@ static LibError dump_sym_array(DWORD type_id, const u8* p, DumpState state)
{
ULONG64 size_ = 0;
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_LENGTH, &size_))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
const size_t size = (size_t)size_;
// get element count and size
DWORD el_type_id = 0;
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_TYPEID, &el_type_id))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
// .. workaround: TI_GET_COUNT returns total struct size for
// arrays-of-struct. therefore, calculate as size / el_size.
ULONG64 el_size_;
if(!SymGetTypeInfo(hProcess, mod_base, el_type_id, TI_GET_LENGTH, &el_size_))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
const size_t el_size = (size_t)el_size_;
debug_assert(el_size != 0);
const size_t num_elements = size/el_size;
@ -1019,10 +1021,10 @@ static LibError dump_sym_base_type(DWORD type_id, const u8* p, DumpState state)
{
DWORD base_type;
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_BASETYPE, &base_type))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
ULONG64 size_ = 0;
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_LENGTH, &size_))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
const size_t size = (size_t)size_;
// single out() call. note: we pass a single u64 for all sizes,
@ -1141,7 +1143,7 @@ display_as_hex:
case btBit:
case btBSTR:
case btHresult:
return ERR_SYM_UNSUPPORTED;
return ERR_SYM_UNSUPPORTED; // NOWARN
}
out(fmt, data);
@ -1165,14 +1167,14 @@ static LibError dump_sym_base_class(DWORD type_id, const u8* p, DumpState state)
{
DWORD base_class_type_id;
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_TYPEID, &base_class_type_id))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
// this is a virtual base class. we can't display those because it'd
// require reading the VTbl, which is difficult given lack of documentation
// and just not worth it.
DWORD vptr_ofs;
if(SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_VIRTUALBASEPOINTEROFFSET, &vptr_ofs))
return ERR_SYM_UNSUPPORTED;
return ERR_SYM_UNSUPPORTED; // NOWARN
return dump_sym(base_class_type_id, p, state);
@ -1187,7 +1189,7 @@ static LibError dump_sym_data(DWORD id, const u8* p, DumpState state)
// display name (of variable/member)
const wchar_t* name;
if(!SymGetTypeInfo(hProcess, mod_base, id, TI_GET_SYMNAME, &name))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
out(L"%s = ", name);
LocalFree((HLOCAL)name);
@ -1196,7 +1198,7 @@ static LibError dump_sym_data(DWORD id, const u8* p, DumpState state)
// get type_id and address
DWORD type_id;
if(!SymGetTypeInfo(hProcess, mod_base, id, TI_GET_TYPEID, &type_id))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
LibError ret = determine_symbol_address(id, type_id, &p);
if(ret != 0)
return ret;
@ -1206,7 +1208,7 @@ static LibError dump_sym_data(DWORD id, const u8* p, DumpState state)
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return ERR_SYM_INTERNAL_ERROR;
return ERR_SYM_INTERNAL_ERROR; // NOWARN
}
}
@ -1217,7 +1219,7 @@ static LibError dump_sym_enum(DWORD type_id, const u8* p, DumpState UNUSED(state
{
ULONG64 size_ = 0;
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_LENGTH, &size_))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
const size_t size = (size_t)size_;
const i64 enum_value = movsx_64le(p, size);
@ -1225,10 +1227,10 @@ static LibError dump_sym_enum(DWORD type_id, const u8* p, DumpState UNUSED(state
// get array of child symbols (enumerants).
DWORD num_children;
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_CHILDRENCOUNT, &num_children))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
TI_FINDCHILDREN_PARAMS2 fcp(num_children);
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_FINDCHILDREN, &fcp))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
num_children = fcp.p.Count; // was truncated to MAX_CHILDREN
const DWORD* children = fcp.p.ChildId;
@ -1244,7 +1246,7 @@ static LibError dump_sym_enum(DWORD type_id, const u8* p, DumpState UNUSED(state
// already pulled in by e.g. OpenGL anyway.
VARIANT v;
if(!SymGetTypeInfo(hProcess, mod_base, child_data_id, TI_GET_VALUE, &v))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
if(VariantChangeType(&v, &v, 0, VT_I8) != S_OK)
continue;
@ -1253,7 +1255,7 @@ static LibError dump_sym_enum(DWORD type_id, const u8* p, DumpState UNUSED(state
{
const wchar_t* name;
if(!SymGetTypeInfo(hProcess, mod_base, child_data_id, TI_GET_SYMNAME, &name))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
out(L"%s", name);
LocalFree((HLOCAL)name);
return ERR_OK;
@ -1274,7 +1276,7 @@ static LibError dump_sym_enum(DWORD type_id, const u8* p, DumpState UNUSED(state
static LibError dump_sym_function(DWORD UNUSED(type_id), const u8* UNUSED(p),
DumpState UNUSED(state))
{
return ERR_SYM_SUPPRESS_OUTPUT;
return ERR_SYM_SUPPRESS_OUTPUT; // NOWARN
}
@ -1334,7 +1336,7 @@ static LibError dump_sym_pointer(DWORD type_id, const u8* p, DumpState state)
{
ULONG64 size_ = 0;
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_LENGTH, &size_))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
const size_t size = (size_t)size_;
// read+output pointer's value.
@ -1360,11 +1362,11 @@ static LibError dump_sym_pointer(DWORD type_id, const u8* p, DumpState state)
// the responsible dump_sym* will erase "->", leaving only address.
out(L" -> ");
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_TYPEID, &type_id))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
// prevent infinite recursion just to be safe (shouldn't happen)
if(state.indirection >= MAX_INDIRECTION)
return ERR_SYM_NESTING_LIMIT;
WARN_RETURN(ERR_SYM_NESTING_LIMIT);
state.indirection++;
return dump_sym(type_id, p, state);
}
@ -1376,7 +1378,7 @@ static LibError dump_sym_pointer(DWORD type_id, const u8* p, DumpState state)
static LibError dump_sym_typedef(DWORD type_id, const u8* p, DumpState state)
{
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_TYPEID, &type_id))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
return dump_sym(type_id, p, state);
}
@ -1410,11 +1412,11 @@ static LibError udt_get_child_type(const wchar_t* child_name,
// .. its type information is what we want.
DWORD type_id;
if(!SymGetTypeInfo(hProcess, mod_base, child_id, TI_GET_TYPEID, &type_id))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
ULONG64 size;
if(!SymGetTypeInfo(hProcess, mod_base, child_id, TI_GET_LENGTH, &size))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
*el_type_id = type_id;
*el_size = (size_t)size;
@ -1422,7 +1424,7 @@ static LibError udt_get_child_type(const wchar_t* child_name,
}
// (happens if called for containers that are treated as STL but are not)
return ERR_SYM_CHILD_NOT_FOUND;
return ERR_SYM_CHILD_NOT_FOUND; // NOWARN
}
@ -1597,7 +1599,7 @@ static LibError udt_dump_normal(const wchar_t* type_name, const u8* p, size_t si
// prevent infinite recursion just to be safe (shouldn't happen)
if(state.level >= MAX_LEVEL)
return ERR_SYM_NESTING_LIMIT;
WARN_RETURN(ERR_SYM_NESTING_LIMIT);
state.level++;
out(fits_on_one_line? L"{ " : L"\r\n");
@ -1663,22 +1665,22 @@ static LibError dump_sym_udt(DWORD type_id, const u8* p, DumpState state)
{
ULONG64 size_ = 0;
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_LENGTH, &size_))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
const size_t size = (size_t)size_;
// get array of child symbols (members/functions/base classes).
DWORD num_children;
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_CHILDRENCOUNT, &num_children))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
TI_FINDCHILDREN_PARAMS2 fcp(num_children);
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_FINDCHILDREN, &fcp))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
num_children = fcp.p.Count; // was truncated to MAX_CHILDREN
const DWORD* children = fcp.p.ChildId;
const wchar_t* type_name;
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_SYMNAME, &type_name))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
LibError ret;
// note: order is important (e.g. STL special-case must come before
@ -1708,7 +1710,7 @@ done:
static LibError dump_sym_vtable(DWORD UNUSED(type_id), const u8* UNUSED(p), DumpState UNUSED(state))
{
// unsupported (vtable internals are undocumented; too much work).
return ERR_SYM_SUPPRESS_OUTPUT;
return ERR_SYM_SUPPRESS_OUTPUT; // NOWARN
}
@ -1720,7 +1722,7 @@ static LibError dump_sym_unknown(DWORD type_id, const u8* UNUSED(p), DumpState U
// redundant (already done in dump_sym), but this is rare.
DWORD type_tag;
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_SYMTAG, &type_tag))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
debug_printf("SYM| unknown tag: %d\n", type_tag);
out(L"(unknown symbol type)");
@ -1739,7 +1741,7 @@ static LibError dump_sym(DWORD type_id, const u8* p, DumpState state)
DWORD type_tag;
if(!SymGetTypeInfo(hProcess, mod_base, type_id, TI_GET_SYMTAG, &type_tag))
return ERR_SYM_TYPE_INFO_UNAVAILABLE;
WARN_RETURN(ERR_SYM_TYPE_INFO_UNAVAILABLE);
switch(type_tag)
{
case SymTagArrayType:

View File

@ -104,7 +104,7 @@ LibError get_cur_vmode(int* xres, int* yres, int* bpp, int* freq)
// dm.dmDriverExtra already set to 0 by memset
if(!EnumDisplaySettingsA(0, ENUM_CURRENT_SETTINGS, &dm))
return ERR_FAIL;
WARN_RETURN(ERR_FAIL);
if(dm.dmFields & (DWORD)DM_PELSWIDTH && xres)
*xres = (int)dm.dmPelsWidth;
@ -144,10 +144,10 @@ static LibError get_ver(const char* module_path, char* out_ver, size_t out_ver_l
DWORD unused;
const DWORD ver_size = GetFileVersionInfoSize(module_path, &unused);
if(!ver_size)
return ERR_FAIL;
WARN_RETURN(ERR_FAIL);
void* buf = malloc(ver_size);
if(!buf)
return ERR_NO_MEM;
WARN_RETURN(ERR_NO_MEM);
LibError ret = ERR_FAIL; // single point of exit (for free())
@ -200,12 +200,9 @@ static void dll_list_init(char* buf, size_t chars)
// we add the .dll extension if necessary.
static LibError dll_list_add(const char* name)
{
// make sure we're allowed to be called.
// not be called before dll_list_init or after failure
if(!dll_list_pos)
{
debug_warn("called before dll_list_init or after failure");
return ERR_FAIL;
}
WARN_RETURN(ERR_LOGIC);
// some driver names are stored in the registry without .dll extension.
// if necessary, copy to new buffer and add it there.
@ -247,8 +244,7 @@ static LibError dll_list_add(const char* name)
// didn't fit; complain
sprintf(dll_list_pos, "..."); // (room was reserved above)
dll_list_pos = 0; // poison pill, prevent further calls
debug_warn("not enough room");
return ERR_BUF_SIZE;
WARN_RETURN(ERR_BUF_SIZE);
}
@ -287,7 +283,7 @@ static LibError win_get_gfx_card()
}
}
return ERR_FAIL;
WARN_RETURN(ERR_FAIL);
}
@ -296,7 +292,7 @@ static LibError win_get_gfx_drv_ver()
{
// don't overwrite existing information
if(gfx_drv_ver[0] != '\0')
return ERR_FAIL;
return INFO_SKIPPED;
// rationale:
// - we could easily determine the 2d driver via EnumDisplaySettings,
@ -324,7 +320,7 @@ static LibError win_get_gfx_drv_ver()
HKEY hkOglDrivers;
const char* key = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\OpenGLDrivers";
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hkOglDrivers) != 0)
return ERR_FAIL;
WARN_RETURN(ERR_FAIL);
// for each subkey (i.e. set of installed OpenGL drivers):
for(i = 0; ; i++)

View File

@ -276,14 +276,12 @@ fail:
LibError dir_cancel_watch(const intptr_t reqnum)
{
if(reqnum <= 0)
return ERR_INVALID_PARAM;
WARN_RETURN(ERR_INVALID_PARAM);
Watch* w = find_watch(reqnum);
// watches[reqnum] is invalid - big trouble
if(!w)
{
debug_warn("watches[reqnum] invalid");
return ERR_FAIL;
}
WARN_RETURN(ERR_FAIL);
// we're freeing a reference - done.
debug_assert(w->refs >= 1);
@ -383,7 +381,7 @@ LibError dir_get_changed_file(char* fn)
// nothing to return; call again later.
if(pending_events.empty())
return ERR_AGAIN;
return ERR_AGAIN; // NOWARN
const std::string& fn_s = pending_events.front();
strcpy_s(fn, PATH_MAX, fn_s.c_str());

View File

@ -33,29 +33,33 @@ char win_exe_dir[MAX_PATH+1];
// only call after a Win32 function indicates failure.
static LibError LibError_from_GLE()
static LibError LibError_from_GLE(bool warn_if_failed = true)
{
LibError err;
switch(GetLastError())
{
case ERROR_OUTOFMEMORY:
return ERR_NO_MEM;
err = ERR_NO_MEM; break;
case ERROR_INVALID_PARAMETER:
return ERR_INVALID_PARAM;
err = ERR_INVALID_PARAM; break;
case ERROR_INSUFFICIENT_BUFFER:
return ERR_BUF_SIZE;
err = ERR_BUF_SIZE; break;
case ERROR_ACCESS_DENIED:
return ERR_FILE_ACCESS;
err = ERR_FILE_ACCESS; break;
case ERROR_FILE_NOT_FOUND:
return ERR_FILE_NOT_FOUND;
err = ERR_FILE_NOT_FOUND; break;
case ERROR_PATH_NOT_FOUND:
return ERR_PATH_NOT_FOUND;
err = ERR_PATH_NOT_FOUND; break;
default:
return ERR_FAIL;
err = ERR_FAIL; break;
}
UNREACHABLE;
if(warn_if_failed)
DEBUG_WARN_ERR(err);
return err;
}
@ -63,9 +67,11 @@ static LibError LibError_from_GLE()
// there's no equal.
// you should SetLastError(0) before calling whatever will set ret
// to make sure we do not return any stale errors.
LibError LibError_from_win32(DWORD ret)
LibError LibError_from_win32(DWORD ret, bool warn_if_failed)
{
return (ret != FALSE)? ERR_OK : LibError_from_GLE();
if(ret != FALSE)
return ERR_OK;
return LibError_from_GLE(warn_if_failed);
}

View File

@ -454,7 +454,7 @@ extern void win_free(void* p);
// there's no equal.
// you should SetLastError(0) before calling whatever will set ret
// to make sure we do not return any stale errors.
extern LibError LibError_from_win32(DWORD ret);
extern LibError LibError_from_win32(DWORD ret, bool warn_if_failed = true);
extern char win_sys_dir[MAX_PATH+1];

View File

@ -94,7 +94,7 @@ no_aio:
// warn now, so that we notice why so many are open.
#ifndef NDEBUG
if(fd > 256)
debug_warn("wposix: too many files open (CRT limitation)");
WARN_ERR(ERR_LIMIT);
#endif
return fd;
@ -407,7 +407,7 @@ fail:
goto success;
// translate Win32 error to errno.
LibError err = LibError_from_win32(0);
LibError err = LibError_from_win32(FALSE);
LibError_set_errno(err);
// release the WDIR allocated above.
@ -630,7 +630,7 @@ static LibError mmap_mem(void* start, size_t len, int prot, int flags, int fd, v
DWORD flProtect = win32_prot(prot);
void* p = VirtualAlloc(start, len, flAllocationType, flProtect);
if(!p)
return ERR_NO_MEM;
WARN_RETURN(ERR_NO_MEM);
*pp = p;
return ERR_OK;
}
@ -665,7 +665,7 @@ static LibError mmap_file_access(int prot, int flags, DWORD& flProtect, DWORD& d
// definitely illegal according to POSIX and some man pages
// say exactly one must be set, so abort.
default:
return ERR_INVALID_PARAM;
WARN_RETURN(ERR_INVALID_PARAM);
}
}
@ -682,7 +682,7 @@ static LibError mmap_file(void* start, size_t len, int prot, int flags,
HANDLE hFile = HANDLE_from_intptr(_get_osfhandle(fd));
if(hFile == INVALID_HANDLE_VALUE)
return ERR_INVALID_PARAM;
WARN_RETURN(ERR_INVALID_PARAM);
// MapViewOfFileEx will fail if the "suggested" base address is
// nonzero but cannot be honored, so wipe out <start> unless MAP_FIXED.
@ -699,7 +699,7 @@ static LibError mmap_file(void* start, size_t len, int prot, int flags,
const HANDLE hMap = CreateFileMapping(hFile, 0, flProtect, 0, 0, (LPCSTR)0);
// .. create failed; bail now to avoid overwriting the last error value.
if(!hMap)
return ERR_NO_MEM;
WARN_RETURN(ERR_NO_MEM);
const DWORD ofs_hi = u64_hi(ofs), ofs_lo = u64_lo(ofs);
void* p = MapViewOfFileEx(hMap, dwAccess, ofs_hi, ofs_lo, (SIZE_T)len, start);
// .. make sure we got the requested address if MAP_FIXED was passed.
@ -710,7 +710,7 @@ static LibError mmap_file(void* start, size_t len, int prot, int flags,
CloseHandle(hMap);
// .. map failed; bail now to avoid "restoring" the last error value.
if(!p)
return ERR_NO_MEM;
WARN_RETURN(ERR_NO_MEM);
// slap on correct (more restrictive) permissions.
(void)mprotect(p, len, prot);

View File

@ -351,7 +351,7 @@ LibError sys_clipboard_set(const wchar_t* text)
// MSDN: passing 0 requests the current task be granted ownership;
// there's no need to pass our window handle.
if(!OpenClipboard(new_owner))
return ERR_FAIL;
WARN_RETURN(ERR_FAIL);
EmptyClipboard();
LibError err = ERR_FAIL;
@ -494,7 +494,7 @@ LibError sys_cursor_create(uint w, uint h, void* bgra_img,
DeleteObject(hbmColour);
if(!hIcon) // not INVALID_HANDLE_VALUE
return ERR_FAIL;
WARN_RETURN(ERR_FAIL);
*cursor = ptr_from_HICON(hIcon);
return ERR_OK;
@ -550,7 +550,7 @@ LibError sys_error_description_r(int err, char* buf, size_t max_chars)
{
// not in our range (Win32 error numbers are positive)
if(err < 0)
return ERR_FAIL;
return ERR_FAIL; // NOWARN
const LPCVOID source = 0; // ignored (we're not using FROM_HMODULE etc.)
const DWORD lang_id = 0; // look for neutral, then current locale
@ -558,7 +558,7 @@ LibError sys_error_description_r(int err, char* buf, size_t max_chars)
DWORD chars_output = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, source, (DWORD)err,
lang_id, buf, (DWORD)max_chars, args);
if(!chars_output)
return ERR_FAIL;
WARN_RETURN(ERR_FAIL);
debug_assert(chars_output < max_chars);
return ERR_OK;
}
@ -654,11 +654,11 @@ LibError sys_on_each_cpu(void (*cb)())
const HANDLE hProcess = GetCurrentProcess();
DWORD process_affinity, system_affinity;
if(!GetProcessAffinityMask(hProcess, &process_affinity, &system_affinity))
return ERR_FAIL;
WARN_RETURN(ERR_FAIL);
// our affinity != system affinity: OS is limiting the CPUs that
// this process can run on. fail (cannot call back for each CPU).
if(process_affinity != system_affinity)
return ERR_FAIL;
WARN_RETURN(ERR_CPU_RESTRICTED_AFFINITY);
for(DWORD cpu_bit = 1; cpu_bit != 0 && cpu_bit <= process_affinity; cpu_bit *= 2)
{
@ -668,7 +668,7 @@ LibError sys_on_each_cpu(void (*cb)())
// .. and do so.
if(!SetProcessAffinityMask(hProcess, process_affinity))
{
debug_warn("SetProcessAffinityMask failed");
WARN_ERR(ERR_CPU_RESTRICTED_AFFINITY);
continue;
}

View File

@ -278,10 +278,9 @@ static LibError choose_impl()
return ERR_OK;
}
debug_warn("no safe timer found!");
hrt_impl = HRT_NONE;
hrt_nominal_freq = -1.0;
return ERR_FAIL;
WARN_RETURN(ERR_TIMER_NO_SAFE_IMPL);
}