first batch of resource-handling functions
This commit is contained in:
parent
8fb7d0ac0b
commit
8aa4b9a2ed
204
src/resources.c
204
src/resources.c
|
@ -17,6 +17,8 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <zip.h>
|
||||
#include "wintype.h"
|
||||
#include "scode.h"
|
||||
|
@ -24,6 +26,17 @@
|
|||
#include "log.h"
|
||||
#include "resources.h"
|
||||
|
||||
typedef struct tagRESFILE {
|
||||
struct tagRESFILE *next;
|
||||
struct tagRESFILE *prev;
|
||||
zip_t *resource;
|
||||
} RESFILE, *PRESFILE;
|
||||
|
||||
typedef struct tagRESOURCEINFO {
|
||||
zip_t *resource_file;
|
||||
zip_stat_t entryinfo;
|
||||
} RESOURCEINFO, *PRESOURCEINFO;
|
||||
|
||||
/* conversion table from zip error codes to our HRESULT values */
|
||||
static const struct tagCONVERSIONTABLE {
|
||||
int zip_err_code;
|
||||
|
@ -46,6 +59,7 @@ extern uint8_t _binary_sysresources_zip_end;
|
|||
extern uint8_t _binary_sysresources_zip_size;
|
||||
|
||||
static zip_t *sysresource = NULL; /* system resource file */
|
||||
static PRESFILE resfiles = NULL; /* all open resource files */
|
||||
|
||||
static HRESULT ziperror_to_hresult(zip_error_t *errinfo)
|
||||
{
|
||||
|
@ -57,8 +71,198 @@ static HRESULT ziperror_to_hresult(zip_error_t *errinfo)
|
|||
return MAKE_SCODE(SEVERITY_ERROR, FACILITY_ZIP, errinfo->zip_err);
|
||||
}
|
||||
|
||||
static BOOL check_in_list(PRESFILE presfile)
|
||||
{
|
||||
register PRESFILE p = resfiles;
|
||||
do
|
||||
{
|
||||
if (p == presfile)
|
||||
return TRUE;
|
||||
p = p->next;
|
||||
} while (p != resfiles);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HRESULT Rsrc_load_file(LPCSTR filename, PHRESFILE newhandle)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
PRESFILE pfile = NULL;
|
||||
zip_error_t errinfo;
|
||||
|
||||
if (!newhandle)
|
||||
return E_POINTER;
|
||||
*newhandle = NULL;
|
||||
|
||||
pfile = (PRESFILE)malloc(sizeof(RESFILE));
|
||||
if (!pfile)
|
||||
return E_OUTOFMEMORY;
|
||||
memset(pfile, 0, sizeof(RESFILE));
|
||||
|
||||
zip_error_init(&errinfo);
|
||||
pfile->resource = zip_open(filename, ZIP_RDONLY, &errinfo);
|
||||
if (!(pfile->resource))
|
||||
hr = ziperror_to_hresult(&errinfo);
|
||||
zip_error_fini(&errinfo);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (resfiles)
|
||||
{
|
||||
pfile->next = resfiles;
|
||||
pfile->prev = resfiles->prev;
|
||||
resfiles->prev->next = pfile;
|
||||
resfiles->prev = pfile;
|
||||
}
|
||||
else
|
||||
pfile->next = pfile->prev = pfile;
|
||||
resfiles = pfile;
|
||||
*newhandle = (HRESFILE)pfile;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT internal_close(PRESFILE presfile)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (zip_close(presfile->resource))
|
||||
hr = ziperror_to_hresult(zip_get_error(presfile->resource));
|
||||
if (resfiles == presfile)
|
||||
{
|
||||
resfiles = presfile->next;
|
||||
if (resfiles == presfile)
|
||||
resfiles = NULL;
|
||||
}
|
||||
presfile->prev->next = presfile->next;
|
||||
presfile->next->prev = presfile->prev;
|
||||
free(presfile);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT Rsrc_close_file(HRESFILE handle)
|
||||
{
|
||||
if (check_in_list((PRESFILE)handle))
|
||||
return internal_close((PRESFILE)handle);
|
||||
return E_HANDLE;
|
||||
}
|
||||
|
||||
HRESULT Rsrc_find_resource(HRESFILE hfile, LPCSTR name, LPCSTR type, PHRSRC presource)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
PRESFILE pfile = (PRESFILE)hfile;
|
||||
PRESOURCEINFO info = NULL;
|
||||
zip_t *theresource;
|
||||
zip_int64_t index;
|
||||
|
||||
if (pfile)
|
||||
{
|
||||
if (check_in_list(pfile))
|
||||
theresource = pfile->resource;
|
||||
else
|
||||
return E_HANDLE;
|
||||
}
|
||||
else
|
||||
theresource = sysresource;
|
||||
ASSERT(theresource);
|
||||
if (!name)
|
||||
return E_INVALIDARG;
|
||||
if (!presource)
|
||||
return E_POINTER;
|
||||
*presource = NULL;
|
||||
|
||||
index = zip_name_locate(theresource, name, ZIP_FL_NOCASE);
|
||||
if (index < 0)
|
||||
hr = ziperror_to_hresult(zip_get_error(theresource));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
info = (PRESOURCEINFO)malloc(sizeof(RESOURCEINFO));
|
||||
if (info)
|
||||
{
|
||||
if (zip_stat_index(theresource, index, ZIP_FL_NOCASE, &(info->entryinfo)))
|
||||
hr = ziperror_to_hresult(zip_get_error(theresource));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
info->entryinfo.index = index;
|
||||
info->entryinfo.valid |= ZIP_STAT_INDEX;
|
||||
info->resource_file = theresource;
|
||||
*presource = (HRSRC)info;
|
||||
}
|
||||
if (FAILED(hr))
|
||||
free(info);
|
||||
}
|
||||
else
|
||||
hr = E_OUTOFMEMORY;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT Rsrc_free_resource(HRSRC resource)
|
||||
{
|
||||
if (!resource)
|
||||
return E_HANDLE;
|
||||
free((PRESOURCEINFO)resource);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
UINT Rsrc_sizeof_resource(HRSRC resource)
|
||||
{
|
||||
PRESOURCEINFO p = (PRESOURCEINFO)resource;
|
||||
if (!p)
|
||||
return 0;
|
||||
if (p->entryinfo.valid & ZIP_STAT_SIZE)
|
||||
return (UINT)(p->entryinfo.size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HRESULT Rsrc_read_resource_here(HRSRC resource, PVOID buffer, UINT size, PUINT actual_read)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
PRESOURCEINFO p = (PRESOURCEINFO)resource;
|
||||
UINT max_size = size;
|
||||
UINT already_read = 0;
|
||||
PBYTE pbuffer = (PBYTE)buffer;
|
||||
zip_int64_t nread;
|
||||
zip_file_t *fp;
|
||||
|
||||
if (!p)
|
||||
return E_HANDLE;
|
||||
if (!buffer)
|
||||
return E_POINTER;
|
||||
if (p->entryinfo.valid & ZIP_STAT_SIZE)
|
||||
{
|
||||
if ((UINT)(p->entryinfo.size) < max_size)
|
||||
max_size = (UINT)(p->entryinfo.size);
|
||||
else if ((UINT)(p->entryinfo.size) > max_size)
|
||||
hr = UPIWIN_S_PARTIALRSRC;
|
||||
}
|
||||
|
||||
fp = zip_fopen_index(p->resource_file, p->entryinfo.index, ZIP_FL_NOCASE);
|
||||
if (fp)
|
||||
{
|
||||
while (SUCCEEDED(hr) && (max_size > 0))
|
||||
{
|
||||
nread = zip_fread(fp, pbuffer, max_size);
|
||||
if (nread < 0)
|
||||
{
|
||||
hr = ziperror_to_hresult(zip_get_error(p->resource_file));
|
||||
break;
|
||||
}
|
||||
pbuffer += (UINT_PTR)nread;
|
||||
max_size -= (UINT)nread;
|
||||
already_read += (UINT)nread;
|
||||
}
|
||||
zip_fclose(fp);
|
||||
}
|
||||
else
|
||||
hr = ziperror_to_hresult(zip_get_error(p->resource_file));
|
||||
if (actual_read)
|
||||
*actual_read = already_read;
|
||||
return hr;
|
||||
}
|
||||
|
||||
static void rsrc_cleanup(void)
|
||||
{
|
||||
while (resfiles)
|
||||
internal_close(resfiles);
|
||||
zip_close(sysresource);
|
||||
sysresource = NULL;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,15 @@
|
|||
typedef HANDLE HRESFILE; /* handle to resource file */
|
||||
typedef HANDLE HRSRC; /* handle to resource */
|
||||
|
||||
typedef HRESFILE *PHRESFILE;
|
||||
typedef HRSRC *PHRSRC;
|
||||
|
||||
extern HRESULT Rsrc_load_file(LPCSTR filename, PHRESFILE newhandle);
|
||||
extern HRESULT Rsrc_close_file(HRESFILE handle);
|
||||
extern HRESULT Rsrc_find_resource(HRESFILE hfile, LPCSTR name, LPCSTR type, PHRSRC presource);
|
||||
extern HRESULT Rsrc_free_resource(HRSRC resource);
|
||||
extern UINT Rsrc_sizeof_resource(HRSRC resource);
|
||||
extern HRESULT Rsrc_read_resource_here(HRSRC resource, PVOID buffer, UINT size, PUINT actual_read);
|
||||
|
||||
extern HRESULT Rsrc_setup(void);
|
||||
|
||||
|
|
|
@ -107,6 +107,8 @@
|
|||
#define UPIWIN_E_INVALIDSCRIPT SCODE_CAST(0x80060000) /* invalid script file */
|
||||
#define UPIWIN_E_NOSCRIPT SCODE_CAST(0x80060001) /* no script specified */
|
||||
|
||||
#define UPIWIN_S_PARTIALRSRC SCODE_CAST(0x00060000) /* partial resource read */
|
||||
|
||||
/* libzip error codes */
|
||||
#define ZIP_E_MULTIDISK MAKE_SCODE(SEVERITY_ERROR, FACILITY_ZIP, 1) /* multidisk not supported */
|
||||
#define ZIP_E_RENAME MAKE_SCODE(SEVERITY_ERROR, FACILITY_ZIP, 2) /* rename temp file failed */
|
||||
|
|
Loading…
Reference in New Issue
Block a user