#include "image.h"
 
#include "CORE/FW/loader.h"
 
#include "CORE/FW/brlists.h"
 
#include "CORE/FW/fwsetup.h"
 
#include "CORE/FW/pattern.h"
 
#include "CORE/FW/resource.h"
 
#include "CORE/FW/scratch.h"
 
#include "CORE/HOST/himage.h"
 
#include "CORE/STD/brstdlib.h"
 
#include "harness/trace.h"
 
 
 
// IDA: br_boolean __cdecl BrImageAdd(br_image *img)
 
/*br_boolean*/void BrImageAdd(br_image* img) { // Pierre-Marie Baty -- fixed type
 
    LOG_TRACE("(%p)", img);
 
 
 
    BrAddHead(&fw.images, &img->node);
 
}
 
 
 
// IDA: br_boolean __cdecl BrImageRemove(br_image *img)
 
/*br_boolean*/void BrImageRemove(br_image* img) { // Pierre-Marie Baty -- fixed type
 
    LOG_TRACE("(%p)", img);
 
 
 
    BrRemove(&img->node);
 
}
 
 
 
// IDA: br_image* __cdecl BrImageFind(char *pattern)
 
br_image* BrImageFind(char* pattern) {
 
    char* c;
 
    br_image* img;
 
    LOG_TRACE("(\"%s\")", pattern);
 
 
 
    c = BrStrRChr(pattern, '.');
 
    if (c != NULL && (BrStrCmp(c, ".dll") == 0 || BrStrCmp(c, ".bdd") == 0|| BrStrCmp(c, "bed"))) {
 
        *c = '\0';
 
    }
 
    for (img = (br_image*)fw.images.head; img->node.next != NULL; img = (br_image*)img->node.next) {
 
        if (BrNamePatternMatch(pattern, img->identifier) != 0) {
 
            return img;
 
        }
 
    }
 
    return NULL;
 
}
 
 
 
// IDA: br_image* __usercall imageLoadHost@<EAX>(char *name@<EAX>)
 
br_image* imageLoadHost(char* name) {
 
    br_image* img;
 
    void* host_image;
 
    LOG_TRACE("(\"%s\")", name);
 
    NOT_IMPLEMENTED();
 
 
 
    host_image = HostImageLoad(name);
 
    if (host_image != NULL) {
 
        img = BrResAllocate(NULL, sizeof(br_image), BR_MEMORY_IMAGE);
 
        img->identifier = BrResStrDup(img, name);
 
        img->type = 3;
 
        img->type_pointer = host_image;
 
    }
 
    return img;
 
}
 
 
 
// IDA: br_image* __cdecl BrImageReference(char *name)
 
br_image* BrImageReference(char* name) {
 
    char* suffix;
 
    char* scratch;
 
    br_image* img;
 
    LOG_TRACE("(\"%s\")", name);
 
 
 
    scratch = BrScratchString();
 
    img = BrImageFind(name);
 
    if (img != NULL) {
 
        img->ref_count++;
 
        return img;
 
    }
 
    for (suffix = name; *suffix != '\0' && *suffix != '.'; suffix++) {
 
    }
 
    if (*suffix == '\0') {
 
        if (img == NULL) {
 
            BrStrCpy(scratch, name);
 
            BrStrCat(scratch, ".BDD");
 
            img = ImageLoad(name);
 
        }
 
        if (img == NULL) {
 
            img = imageLoadHost(scratch);
 
        }
 
        if (img == NULL) {
 
            BrStrCpy(scratch, name);
 
            BrStrCat(scratch, ".DLL");
 
            img = ImageLoad(scratch);
 
        }
 
    } else if (BrStrCmp(suffix, ".bdd") == 0 || BrStrCmp(suffix, ".bed") == 0) {
 
        if (img == NULL) {
 
            img = ImageLoad(name);
 
        }
 
        if (img == NULL) {
 
            img = imageLoadHost(name);
 
        }
 
    } else {
 
        if (img == NULL) {
 
            img = imageLoadHost(name);
 
        }
 
        if (img == NULL) {
 
            img = ImageLoad(name);
 
        }
 
    }
 
 
 
    if (img != NULL) {
 
        BrResAdd(fw.res, img);
 
        BrAddHead(&fw.images, &img->node);
 
    }
 
    return img;
 
}
 
 
 
// IDA: void* __usercall imageLookupName@<EAX>(br_image *img@<EAX>, char *name@<EDX>, br_uint_32 hint@<EBX>)
 
void* imageLookupName(br_image* img, char* name, br_uint_32 hint) {
 
    int c;
 
    int limit;
 
    int base;
 
    LOG_TRACE("(%p, \"%s\", %d)", img, name, hint);
 
 
 
    if (hint < img->n_names && BrStrCmp(name, img->names[hint]) == 0) {
 
        return img->functions[img->name_ordinals[hint]];
 
    }
 
    base = 0;
 
    limit = img->n_names;
 
    while (1) {
 
        if (limit == 0) {
 
            return NULL;
 
        }
 
        c = BrStrCmp(name, img->names[base + limit / 2]);
 
        if (c == 0) {
 
            return img->functions[img->name_ordinals[base + limit / 2]];
 
        } else if (c < 0) {
 
            continue;
 
        } else {
 
            base += limit / 2 + 1;
 
            limit = limit - (limit / 2 + 1);
 
        }
 
    }
 
}
 
 
 
// IDA: void* __cdecl BrImageLookupName(br_image *img, char *name, br_uint_32 hint)
 
void* BrImageLookupName(br_image* img, char* name, br_uint_32 hint) {
 
    char* scratch;
 
    void* p;
 
    LOG_TRACE("(%p, \"%s\", %d)", img, name, hint);
 
 
 
    scratch = BrScratchString();
 
    if (img->type == 3) {
 
        return HostImageLookupName(img->type_pointer, name, hint);
 
    }
 
    p = imageLookupName(img, name, hint);
 
    if (p != NULL) {
 
        return p;
 
    }
 
    if (*name == '_') {
 
        p = imageLookupName(img, &name[1], hint);
 
        if (p != NULL) {
 
            return p;
 
        }
 
    }
 
    *scratch = '_';
 
    BrStrCpy(&scratch[1], name);
 
    return imageLookupName(img, scratch, hint);
 
}
 
 
 
// IDA: void* __cdecl BrImageLookupOrdinal(br_image *img, br_uint_32 ordinal)
 
void* BrImageLookupOrdinal(br_image* img, br_uint_32 ordinal) {
 
    LOG_TRACE("(%p, %d)", img, ordinal);
 
 
 
    if (img->type == 3) {
 
        return HostImageLookupOrdinal(img->type_pointer, ordinal);
 
    }
 
    if (img->n_functions < (ordinal - img->ordinal_base)) {
 
        return NULL;
 
    }
 
    return img->functions[ordinal - img->ordinal_base];
 
}
 
 
 
// IDA: void __cdecl BrImageDereference(br_image *image)
 
void BrImageDereference(br_image* image) {
 
    LOG_TRACE("(%p)", image);
 
 
 
    image->ref_count--;
 
 
 
    if (image->ref_count <= 0) {
 
        switch (image->type) {
 
        case 2:
 
            break;
 
        case 3:
 
            HostImageUnload(image->type_pointer);
 
            // fall through
 
        default:
 
            BrRemove(&image->node);
 
            BrResFree(image);
 
        }
 
 
 
    }
 
}
 
 
 
// IDA: void __cdecl BrImageFree(br_image *image)
 
void BrImageFree(br_image* image) {
 
    int i;
 
    LOG_TRACE("(%p)", image);
 
 
 
    for (i = 0; i < image->n_imports; i++) {
 
        BrImageDereference(image->imports[i]);
 
    }
 
}
 
 
 
// IDA: void __cdecl _BrImageFree(void *res, br_uint_8 res_class, br_size_t size)
 
void _BrImageFree(void* res, br_uint_8 res_class, br_size_t size) {
 
    LOG_TRACE("(%p, %d, %d)", res, res_class, size);
 
 
 
    BrImageFree(res);
 
}