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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user