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.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <zip.h>
|
#include <zip.h>
|
||||||
#include "wintype.h"
|
#include "wintype.h"
|
||||||
#include "scode.h"
|
#include "scode.h"
|
||||||
|
@ -24,6 +26,17 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "resources.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 */
|
/* conversion table from zip error codes to our HRESULT values */
|
||||||
static const struct tagCONVERSIONTABLE {
|
static const struct tagCONVERSIONTABLE {
|
||||||
int zip_err_code;
|
int zip_err_code;
|
||||||
|
@ -46,6 +59,7 @@ extern uint8_t _binary_sysresources_zip_end;
|
||||||
extern uint8_t _binary_sysresources_zip_size;
|
extern uint8_t _binary_sysresources_zip_size;
|
||||||
|
|
||||||
static zip_t *sysresource = NULL; /* system resource file */
|
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)
|
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);
|
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)
|
static void rsrc_cleanup(void)
|
||||||
{
|
{
|
||||||
|
while (resfiles)
|
||||||
|
internal_close(resfiles);
|
||||||
zip_close(sysresource);
|
zip_close(sysresource);
|
||||||
sysresource = NULL;
|
sysresource = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,15 @@
|
||||||
typedef HANDLE HRESFILE; /* handle to resource file */
|
typedef HANDLE HRESFILE; /* handle to resource file */
|
||||||
typedef HANDLE HRSRC; /* handle to resource */
|
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);
|
extern HRESULT Rsrc_setup(void);
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,8 @@
|
||||||
#define UPIWIN_E_INVALIDSCRIPT SCODE_CAST(0x80060000) /* invalid script file */
|
#define UPIWIN_E_INVALIDSCRIPT SCODE_CAST(0x80060000) /* invalid script file */
|
||||||
#define UPIWIN_E_NOSCRIPT SCODE_CAST(0x80060001) /* no script specified */
|
#define UPIWIN_E_NOSCRIPT SCODE_CAST(0x80060001) /* no script specified */
|
||||||
|
|
||||||
|
#define UPIWIN_S_PARTIALRSRC SCODE_CAST(0x00060000) /* partial resource read */
|
||||||
|
|
||||||
/* libzip error codes */
|
/* libzip error codes */
|
||||||
#define ZIP_E_MULTIDISK MAKE_SCODE(SEVERITY_ERROR, FACILITY_ZIP, 1) /* multidisk not supported */
|
#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 */
|
#define ZIP_E_RENAME MAKE_SCODE(SEVERITY_ERROR, FACILITY_ZIP, 2) /* rename temp file failed */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user