| | 1 | /* |
| | 2 | * Copyright (c) 2001, 2002 Michael J. Roberts. All Rights Reserved. |
| | 3 | * |
| | 4 | * Please see the accompanying license file, LICENSE.TXT, for information |
| | 5 | * on using and copying this software. |
| | 6 | */ |
| | 7 | /* |
| | 8 | Name |
| | 9 | resldexe.cpp - resource loader - executable file loader |
| | 10 | Function |
| | 11 | Loads resources from the executable file, if possible. |
| | 12 | Notes |
| | 13 | This module is separated from the main resload.cpp module to allow |
| | 14 | the executable resource loader to be omitted from the link. If the |
| | 15 | program doesn't want to be able to load from the executable, the link |
| | 16 | can substitute resnoexe.cpp for this module. |
| | 17 | Modified |
| | 18 | 11/03/01 MJRoberts - Creation |
| | 19 | */ |
| | 20 | |
| | 21 | #include <stddef.h> |
| | 22 | #include <string.h> |
| | 23 | |
| | 24 | #include "t3std.h" |
| | 25 | #include "resload.h" |
| | 26 | #include "vmimage.h" |
| | 27 | |
| | 28 | /* ------------------------------------------------------------------------ */ |
| | 29 | /* |
| | 30 | * Resource loader interface implementation |
| | 31 | */ |
| | 32 | class CVmImageLoaderMres_resload: public CVmImageLoaderMres |
| | 33 | { |
| | 34 | public: |
| | 35 | CVmImageLoaderMres_resload(const char *respath) |
| | 36 | { |
| | 37 | /* remember the path of the resource we're trying to find */ |
| | 38 | respath_ = respath; |
| | 39 | respath_len_ = strlen(respath); |
| | 40 | |
| | 41 | /* we haven't found it yet */ |
| | 42 | found_ = FALSE; |
| | 43 | link_ = 0; |
| | 44 | } |
| | 45 | |
| | 46 | ~CVmImageLoaderMres_resload() |
| | 47 | { |
| | 48 | lib_free_str(link_); |
| | 49 | } |
| | 50 | |
| | 51 | /* add a resource */ |
| | 52 | void add_resource(uint32 seek_ofs, uint32 siz, |
| | 53 | const char *res_name, size_t res_name_len) |
| | 54 | { |
| | 55 | /* |
| | 56 | * if we've already found a match, there's no need to consider |
| | 57 | * anything else |
| | 58 | */ |
| | 59 | if (found_) |
| | 60 | return; |
| | 61 | |
| | 62 | /* check to see if this is the one we're looking for */ |
| | 63 | if (res_name_len == respath_len_ |
| | 64 | && memicmp(respath_, res_name, res_name_len) == 0) |
| | 65 | { |
| | 66 | /* we found it */ |
| | 67 | found_ = TRUE; |
| | 68 | |
| | 69 | /* remember the seek location */ |
| | 70 | res_seek_ = seek_ofs; |
| | 71 | res_size_ = siz; |
| | 72 | } |
| | 73 | } |
| | 74 | |
| | 75 | /* add a resource link */ |
| | 76 | void add_resource(const char *fname, size_t fnamelen, |
| | 77 | const char *res_name, size_t res_name_len) |
| | 78 | { |
| | 79 | /* |
| | 80 | * if we've already found a match, there's no need to consider |
| | 81 | * anything else |
| | 82 | */ |
| | 83 | if (found_) |
| | 84 | return; |
| | 85 | |
| | 86 | /* check to see if this is the one we're looking for */ |
| | 87 | if (res_name_len == respath_len_ |
| | 88 | && memicmp(respath_, res_name, res_name_len) == 0) |
| | 89 | { |
| | 90 | /* we found it */ |
| | 91 | found_ = TRUE; |
| | 92 | |
| | 93 | /* remember the link */ |
| | 94 | link_ = lib_copy_str(fname, fnamelen); |
| | 95 | } |
| | 96 | } |
| | 97 | |
| | 98 | /* did we find the resource? */ |
| | 99 | int found_resource() const { return found_; } |
| | 100 | |
| | 101 | /* get the seek location and size of the resource we found */ |
| | 102 | uint32 get_resource_seek() const { return res_seek_; } |
| | 103 | uint32 get_resource_size() const { return res_size_; } |
| | 104 | |
| | 105 | /* get the local filename link, if it's given as a link */ |
| | 106 | const char *get_link_fname() const { return link_; } |
| | 107 | |
| | 108 | private: |
| | 109 | /* name of the resource we're looking for */ |
| | 110 | const char *respath_; |
| | 111 | size_t respath_len_; |
| | 112 | |
| | 113 | /* flag: we found the resource we're looking for */ |
| | 114 | int found_; |
| | 115 | |
| | 116 | /* seek location and size of the resource we found */ |
| | 117 | uint32 res_seek_; |
| | 118 | uint32 res_size_; |
| | 119 | |
| | 120 | /* local filename link, if the resource is given as a link */ |
| | 121 | char *link_; |
| | 122 | }; |
| | 123 | |
| | 124 | /* ------------------------------------------------------------------------ */ |
| | 125 | /* |
| | 126 | * Try loading a resource from the executable file |
| | 127 | */ |
| | 128 | osfildef *CResLoader::open_exe_res(const char *respath, |
| | 129 | const char *restype) |
| | 130 | { |
| | 131 | osfildef *exe_fp; |
| | 132 | |
| | 133 | /* |
| | 134 | * if we don't have an executable filename stored, or we don't have an |
| | 135 | * executable resource type ID, we can't load the resource |
| | 136 | */ |
| | 137 | if (exe_filename_ == 0 || restype == 0) |
| | 138 | return 0; |
| | 139 | |
| | 140 | /* find the executable file's resources */ |
| | 141 | exe_fp = os_exeseek(exe_filename_, restype); |
| | 142 | |
| | 143 | /* if we found something, try loading from that file */ |
| | 144 | if (exe_fp != 0) |
| | 145 | { |
| | 146 | CVmImageLoaderMres_resload res_ifc(respath); |
| | 147 | |
| | 148 | /* try loading the resources */ |
| | 149 | CVmImageLoader:: |
| | 150 | load_resources_from_fp(exe_fp, exe_filename_, &res_ifc); |
| | 151 | |
| | 152 | /* check to see if we found it */ |
| | 153 | if (res_ifc.found_resource()) |
| | 154 | { |
| | 155 | /* check the type */ |
| | 156 | if (res_ifc.get_link_fname() != 0) |
| | 157 | { |
| | 158 | /* |
| | 159 | * it's a linked local file - close the exe file and open |
| | 160 | * the local file instead |
| | 161 | */ |
| | 162 | osfcls(exe_fp); |
| | 163 | exe_fp = osfoprb(res_ifc.get_link_fname(), OSFOPRB); |
| | 164 | } |
| | 165 | else |
| | 166 | { |
| | 167 | /* we got an exe resource - seek to the starting byte */ |
| | 168 | osfseek(exe_fp, res_ifc.get_resource_seek(), OSFSK_SET); |
| | 169 | } |
| | 170 | } |
| | 171 | else |
| | 172 | { |
| | 173 | /* didn't find it - close and forget the executable file */ |
| | 174 | osfcls(exe_fp); |
| | 175 | exe_fp = 0; |
| | 176 | } |
| | 177 | } |
| | 178 | |
| | 179 | /* return the executable file pointer, if we found the resource */ |
| | 180 | return exe_fp; |
| | 181 | } |
| | 182 | |
| | 183 | /* ------------------------------------------------------------------------ */ |
| | 184 | /* |
| | 185 | * Try loading a resource from a resource library |
| | 186 | */ |
| | 187 | osfildef *CResLoader::open_lib_res(const char *libfile, |
| | 188 | const char *respath) |
| | 189 | { |
| | 190 | osfildef *fp; |
| | 191 | |
| | 192 | /* try opening the file */ |
| | 193 | fp = osfoprb(libfile, OSFTT3IMG); |
| | 194 | |
| | 195 | /* if we couldn't open the file, we can't load the resource */ |
| | 196 | if (fp == 0) |
| | 197 | return 0; |
| | 198 | |
| | 199 | /* set up a resource finder for our resource */ |
| | 200 | CVmImageLoaderMres_resload res_ifc(respath); |
| | 201 | |
| | 202 | /* load the file, so that we can try finding the resource */ |
| | 203 | CVmImageLoader::load_resources_from_fp(fp, libfile, &res_ifc); |
| | 204 | |
| | 205 | /* check to see if we found it */ |
| | 206 | if (res_ifc.found_resource()) |
| | 207 | { |
| | 208 | /* we got it - check the type */ |
| | 209 | if (res_ifc.get_link_fname() != 0) |
| | 210 | { |
| | 211 | /* |
| | 212 | * linked local file - close the library file and open the |
| | 213 | * local file instead |
| | 214 | */ |
| | 215 | osfcls(fp); |
| | 216 | fp = osfoprb(res_ifc.get_link_fname(), OSFOPRB); |
| | 217 | } |
| | 218 | else |
| | 219 | { |
| | 220 | /* embedded resource - seek to the first byte */ |
| | 221 | osfseek(fp, res_ifc.get_resource_seek(), OSFSK_SET); |
| | 222 | } |
| | 223 | |
| | 224 | /* return the library file handle */ |
| | 225 | return fp; |
| | 226 | } |
| | 227 | else |
| | 228 | { |
| | 229 | /* didn't find the resource - close the library */ |
| | 230 | osfcls(fp); |
| | 231 | |
| | 232 | /* tell the caller we didn't find the resource */ |
| | 233 | return 0; |
| | 234 | } |
| | 235 | } |