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