⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 olecod.c

📁 excel to html
💻 C
📖 第 1 页 / 共 3 页
字号:
/*   OLEcode - Generate a Microsoft OLE 2 file from given streams.   Copyright 1998, 1999  Roberto Arturo Tena Sanchez   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *//*   Arturo Tena <arturo@directmail.org> */#include <string.h>#include <stdlib.h>#include <assert.h>#if !(defined( __BORLANDC__ ) || defined( __WIN32__ ))#include "cole.h"#else#include "cole.h.in"#endif#include "support.h"#include "internal.h"#ifdef COLE_VERBOSE#define VERBOSE#else#undef VERBOSE#endif/* warning: some lines are longer than 80 characters */struct str_MY_FILE{    enum    {	real, MY_FILE_list, block_list, root_list    } type;    U32 size;		/* size of list _itself_ */    U32 *blocks;	/* size in big blocks (0x0200) of the information			   that contains this file */    union union_file    {	struct str_real        {	    char *name;	/* file name */	    U32 ppsnumber; /* ppsnumber of pps property in stream_list */        } real;	struct str_MY_FILE *MY_FILE_list;	U32 *block_list;	U8 *root_list;    } file;};typedef struct str_MY_FILE MY_FILE;static MY_FILE Input;static MY_FILE *sbfile;static MY_FILE *SDepot;static MY_FILE *BDepot;static MY_FILE *bbd_list;static MY_FILE *Root;/* starting and sizing blocks (calculated in calculate_blocks()) */static U32 header_blocks;      /* how many blocks takes header */static U32 big_streams_blocks; /* how many blocks takes big streams */static U32 sbfile_blocks;      /* how many blocks takes sbfile (small streams) */static U32 SDepot_blocks;      /* how many blocks takes SDepot */static U32 BDepot_blocks;      /* how many blocks takes BDepot */static U32 Root_blocks;        /* how many blocks takes Root */static U32 sbfile_start_block; /* where sbfile starts */static U32 SDepot_start_block; /* where SDepot starts */static U32 Root_start_block;   /* where Root starts */static U32 BDepot_start_block; /* where BDepot starts */static FILE *output_file;/* the output file OLE2 file */static U8 output_block[0x0200];/* used as buffer to write later to output_file */static U16 pos_block;/*   position inside output_block from where the next write will happen,   when it cames 0x0200 must write the block to output_file and   make pos_block = 0x00 */static U32 next_block;/* number of the next block to be written in output_file.   the first block is -1, the second 0, the third 1 and so on *//* process stage functions */static int process_Root (pps_entry * pps_list, U32 root);static U32 max_pps_referenced (pps_entry * pps_list, U32 node);static U32 max3 (U32 a, U32 b, U32 c, U32 d);static int process_streams (pps_entry * pps_list, pps_entry * root);static int add_stream_to_sbfile_and_SDepot (U32 size, char *name, U32 ppsnumber);static int add_stream_to_Input_and_BDepot (U32 size, char *name, U32 ppsnumber);static int add_entry_to_Root (pps_entry * node, U32 start_block);static U32 add_MY_FILE_entry (MY_FILE * list, U32 size);static int pps2root (U8 pps[0x80], pps_entry * node, U32 start_block);static void reset_links_in_Input (void);static void reset_links_in_BDepot (void);static void reset_links_in_SDepot (void);/* generate starge functions */static int generate_ole2_file (const char *filename, int trunc);static int generate_header (void);static int generate_recursive (MY_FILE * list);static int generate_SDepot (void);static int generate_Root (void);static int generate_BDepot (void);static int generate_real_file (MY_FILE * MY_FILE_file);static int write_block_list (U32 start_count, MY_FILE *list, int write_end_chain);static int write_root_list (MY_FILE * list);static void calculate_blocks (void);/* support functions for both stages */static U32 sum_block_list (MY_FILE * list);/* useless function by now, may be later *//* static U32 sum_MY_FILE_list (MY_FILE * list); */static U32 sum_blocks_MY_FILE_list (MY_FILE * list);static void ends (void);#define size2blocks(s,b) (!(s) ? 1 : (1+((s)-1)/(b)))#define size2blocks_preserve_zero(s,b) (!(s) ? 0 : (1+((s)-1)/(b)))#define clean_block(b,s) memset((b),0xff,(s))#define init_MY_FILE(n, t, s, b, f) { \  (n)->type = t; \  (n)->size = (s); \  (n)->blocks = (b); \  (n)->file.t = (f); \  }#define init_MY_FILE_real(n, t, s, b, f, p) { \  n->type = t; \  n->size = s; \  n->blocks = b; \  n->file.real.name = f; \  n->file.real.ppsnumber = p; \  }#define reset_links() { reset_links_in_Input(); reset_links_in_BDepot(); reset_links_in_SDepot(); }/* if this block is full, write it to output_file and   restart using this block */#define check_output_block_boundary() { \  if (pos_block == 0x0200) { \    test_exitf (fwrite (output_block, 0x0200, 1, output_file) == 1, 1, dummy()); \    next_block++; \    pos_block = 0x00; \    } \  }#define write_until_output_block_boundary(clean) { \  if (pos_block != 0x00) { \    if (clean && pos_block%0x0200) \      clean_block (output_block + pos_block, (pos_block/0x0200 + 1)*0x0200 - pos_block); \    test_exitf (fwrite (output_block, 1, 0x0200, output_file) == 0x0200, 1, dummy ()); \    next_block++; \    pos_block = 0x00; \  } \}#define write_until_output_block_small_boundary(clean) { \  if (pos_block % 0x40) { \    if (clean) \      clean_block (output_block + pos_block, (pos_block/0x40 + 1)*0x40 - pos_block); \    assert (pos_block+(pos_block/0x40 + 1)*0x40 - pos_block == (pos_block/0x40 + 1)*0x40); \    pos_block += (U16)((pos_block/0x40 + 1)*0x40 - pos_block); \  } \}#define write_rest_of_output_block_with_null_pps() { \  if (pos_block != 0x00) { \    int zzzi; \    U16 U16zero = 0x0000U; \    clean_block (output_block + pos_block, 0x0200 - pos_block); \     for (zzzi = 0; zzzi < 4; zzzi++) \      if (zzzi*0x80 >= pos_block) \	fil_swriteU16 (output_block + zzzi*0x80 + 0x40, &U16zero); \    } \  }#define dummy()/* may be should be (means no op, do nothing):#define dummy() {1;}or may be:#define dummy() {;}*//*  Exit codes:  0 = All goes OK.  1 = error writting in OLEfilename, can use perror  2 = trunc == 0 and file exist  3 = can't create OLEfilename, can use perror  10 = Error allocating memory, there's no more memory  11 = Error reading streams files  12 = Error reading stream_list, it's broken*/int__OLEcode (const char *OLEfilename, int trunc, pps_entry * stream_list,	   U32 root){  verbose ("calling: OLEcode ()");  assert (OLEfilename != NULL);  assert (stream_list != NULL);  /* -- init static things -- */  output_file = NULL;  clean_block (output_block, 0x0200);  /* just needed clean up once, for security reasons */  pos_block = 0x00;  next_block = 0xffffffffUL;  /* it need to be 0xffffffffUL, because next time we make next_block++     it must be zero (bad hack? next_block is always 32 bits) */  BDepot = SDepot = bbd_list = NULL;  Root = NULL;  sbfile = NULL;  /* -- allocate initial memory needed for my files (Structure called at HACKING) -- */  /* Input: 5 entries in Input: for sbfile, for SDepot, for BDepot,     for bbd_list and for Root */  init_MY_FILE ((&Input), MY_FILE_list, 5 * sizeof (MY_FILE), NULL,		malloc (Input.size));  /* Input->blocks is not needed */  test_exitf (Input.file.MY_FILE_list != NULL, 10, ends ());  reset_links_in_Input ();  /* bbd_list */  init_MY_FILE (bbd_list, block_list, sizeof (U32), NULL,		malloc (bbd_list->size));  /* bbd_list is not needed */  /* bbd_list->blocks is not needed */  test_exitf (bbd_list->file.block_list != NULL, 10, ends ());  bbd_list->file.block_list[0] = 1;  /* because BDepot starts with 3 entries */  /* BDepot */  init_MY_FILE (BDepot, block_list, 3 * sizeof (U32),		bbd_list->file.block_list, malloc (BDepot->size));  test_exitf (BDepot->file.block_list != NULL, 10, ends ());  BDepot->file.block_list[0] = BDepot->file.block_list[1] =    BDepot->file.block_list[2] = 0;  /* sbfile, SDepot and Root are size 0 by now */  /* sbfile */  init_MY_FILE (sbfile, MY_FILE_list, 0, BDepot->file.block_list, NULL);  /* SDepot */  init_MY_FILE (SDepot, block_list, 0, BDepot->file.block_list + 1, NULL);  /* Root */  init_MY_FILE (Root, root_list, 0, BDepot->file.block_list + 2, NULL);  /* -- process streams -- */  test_call (process_Root (stream_list, root), int);  test_call (process_streams (stream_list, &stream_list[root]), int);  /* how can I call ends() if process_streams fails? */  /* -- actually generate ole2 file -- */  test_call (generate_ole2_file (OLEfilename, trunc), int);  return 0;}/* reviewed when coding ole2 file */static intprocess_Root (pps_entry * pps_list, U32 root){  U32 pps_list_entries;  U32 i;  verbose ("calling: process_Root ()");  pps_list_entries = (1 + max_pps_referenced (pps_list, root));  verboseU32 (pps_list_entries);  for (i = 0; i < pps_list_entries; i++)    test_call (add_entry_to_Root (pps_list + i, 0x00000000UL), int);    /*       start_block = 0x00000000UL is a dummy value.       The real start block:         for files in SDepot is written in Root in generate_real_file(),         for files in BDepot is written in Root in generate_real_file(),         and for sbfile: the default is written in process_streams()		 and the real, if any, is written when generating the first		 small stream in generate_real_file().       But 0x00000000UL is a perfect value to directory entries (type=1)       About sizes: every pps have its size, incluiding sbfile,		 that value will be comparated later in generate_real_file().     */  return 0;}#define MAX(a,b) ((a) > (b) ? (a) : (b))static U32 max3 (U32 a, U32 b, U32 c, U32 d){  U32 m = 0;  /*verbose ("calling: max3 ()");*/  m = MAX (m, a);  m = MAX (m, b);  m = MAX (m, c);  m = MAX (m, d);  return m;}static U32 max_pps_referenced (pps_entry * pps_list, U32 node){  U32 max_pps;  /*verbose ("calling: max_pps_referenced ()");*/  max_pps = max3 (node,      pps_list[node].previous != 0xffffffffUL ? pps_list[node].previous : 0,      pps_list[node].next != 0xffffffffUL ? pps_list[node].next : 0,      pps_list[node].dir != 0xffffffffUL ? pps_list[node].dir : 0);  if (pps_list[node].previous != 0xffffffffUL)    max_pps = MAX (max_pps,		   max_pps_referenced (pps_list, pps_list[node].previous));  if (pps_list[node].next != 0xffffffffUL)    max_pps = MAX (max_pps,		   max_pps_referenced (pps_list, pps_list[node].next));  if (pps_list[node].dir != 0xffffffffUL)    max_pps = MAX (max_pps,		   max_pps_referenced (pps_list, pps_list[node].dir));  return max_pps;}/* reviewed when coding ole2 file */static int process_streams (pps_entry * pps_list, pps_entry * node){  U32 U32end_chain = 0xfffffffeUL;  verbose ("calling: process_streams ()");  test_exitf (node->name[0], 12, dummy());  switch (node->type)  {  case 1:  /* dir */    warning (node->size == 0);    if (node->dir != 0xffffffffUL)      test_call (process_streams (pps_list, &pps_list[node->dir]), int);    if (node->next != 0xffffffffUL)      test_call (process_streams (pps_list, &pps_list[node->next]), int);    break;  case 5:  /* root dir */    assert (*(Root->file.root_list + 0x42) == 5);    /* write the default start block of SDepot: empty if there are no       sbfile at all */    fil_swriteU32 (Root->file.root_list + 0x74, &U32end_chain);    if (node->dir != 0xffffffffUL)      test_call (process_streams (pps_list, &pps_list[node->dir]), int);    if (node->next != 0xffffffffUL)      test_call (process_streams (pps_list, &pps_list[node->next]), int);    break;           case 2:  /* file */    test_exitf (node->dir == 0xffffffffUL, 12, dummy());    if (node->size < 0x1000)          /* must be in sbfile, and its block list in SDepot */      test_call (add_stream_to_sbfile_and_SDepot (		 node->size, node->filename, node->ppsnumber), int)    else /* node->size >= 0x1000 */         /* must be in Input, and its block list in BDepot */      test_call (add_stream_to_Input_and_BDepot (		 node->size, node->filename, node->ppsnumber), int);    if (node->next != 0xffffffffUL)      test_call (process_streams (pps_list, &pps_list[node->next]), int);    break;  default:    return 12;  }  return 0;}/* reviewed when processing Root */static int add_entry_to_Root (pps_entry * node, U32 start_block){  U32 entry_number;  U8 * new_entry_Root;  verbose ("calling: add_entry_to_Root ()");  /* 1. add entry in Root */  entry_number = add_MY_FILE_entry (Root, 0 /*dummy value, not used*/);  test_exitf (entry_number != 0xffffffffUL, 10, dummy ());  new_entry_Root = Root->file.root_list + entry_number * 0x80;   /* 2. write info about the new stream in the new entry in Root */  pps2root (new_entry_Root, node, start_block);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -