summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/aparser/cifs.struct579
-rw-r--r--source/aparser/parsefn.awk24
-rw-r--r--source/aparser/parser.c75
-rw-r--r--source/aparser/parser.h15
-rw-r--r--source/aparser/templates/prs_array_remainder.tpl7
-rw-r--r--source/aparser/templates/prs_array_remainder.tpl~7
-rw-r--r--source/aparser/templates/prs_uint8s.tpl2
-rw-r--r--source/aparser/templates/prs_uint8s_fixed.tpl2
-rw-r--r--source/aparser/templates/prs_wstring_fixed.tpl2
9 files changed, 707 insertions, 6 deletions
diff --git a/source/aparser/cifs.struct b/source/aparser/cifs.struct
new file mode 100644
index 00000000000..8d5cef4d8fc
--- /dev/null
+++ b/source/aparser/cifs.struct
@@ -0,0 +1,579 @@
+module cifs
+
+#define BOOL uint32
+#define UCHAR uint8
+#define USHORT uint16
+#define LONG uint32
+#define ULONG uint32
+#define DWORD uint32
+#define SMB_TIME uint16
+#define SMB_DATE uint16
+
+typedef struct {
+ ULONG low;
+ LONG high;
+} TIME;
+
+typedef struct {
+ ULONG low;
+ ULONG high;
+} hyper;
+
+typedef struct {
+ uint8 cmd;
+ uint8 reserved;
+ uint16 offset;
+} ANDX_INFO;
+
+
+typedef struct {
+ uint8 tag2;
+ fstring protocol;
+} BUF2;
+
+typedef struct {
+ uint16 bcount;
+ BUF2 protocol[*];
+} Q_NEGPROT_0;
+
+typedef struct {
+ uint8 wcount;
+ union ctr[wcount] {
+ case 0 Q_NEGPROT_0 q0;
+ }
+} Q_NEGPROT;
+
+typedef struct {
+ USHORT DialectIndex; /* Index of selected dialect */
+ USHORT SecurityMode; /* Security mode: */
+ /* bit 0: 0 = share, 1 = user */
+ /* bit 1: 1 = use challenge/response */
+ /* authentication */
+ USHORT MaxBufferSize; /* Max transmit buffer size (>= 1024) */
+ USHORT MaxMpxCount; /* Max pending multiplexed requests */
+ USHORT MaxNumberVcs; /* Max VCs between client and server */
+ USHORT RawMode; /* Raw modes supported: */
+ /* bit 0: 1 = Read Raw supported */
+ /* bit 1: 1 = Write Raw supported */
+ ULONG SessionKey; /* Unique token identifying this session */
+ SMB_TIME ServerTime; /* Current time at server */
+ SMB_DATE ServerDate; /* Current date at server */
+ USHORT ServerTimeZone; /* Current time zone at server */
+ USHORT ChallengeLength; /* Length of Challenge; MBZ if not LM2.1
+ /* dialect or later */
+ USHORT Reserved; /* MBZ */
+ USHORT ByteCount; /* Count of data bytes */
+ UCHAR Challenge[ChallengeLength]; /* The challenge */
+ fstring PrimaryDomain; /* The server's primary domain */
+
+ uint16 bcount;
+ uint8 chal[8];
+ fstring domain;
+} R_NEGPROT_12;
+
+typedef struct {
+ USHORT DialectIndex; /*Index of selected dialect */
+ UCHAR SecurityMode; /*Security mode: */
+ /* bit 0: 0 = share, 1 = user */
+ /* bit 1: 1 = use challenge/response */
+ /* authentication */
+ /* bit 2: 1 = Security Signatures (SMB integrity */
+ /* check) enabled */
+ /* bit 3: 1 = Security Signatures (SMB integrity */
+ /* check) required */
+ USHORT MaxMpxCount; /*Max pending outstanding requests */
+ USHORT MaxNumberVcs; /*Max VCs between client and server */
+ ULONG MaxBufferSize; /*Max transmit buffer size */
+ ULONG MaxRawSize; /*Maximum raw buffer size */
+ ULONG SessionKey; /*Unique token identifying this session */
+ ULONG Capabilities; /*Server capabilities */
+ ULONG SystemTimeLow; /*System (UTC) time of the server (low). */
+ ULONG SystemTimeHigh; /*System (UTC) time of the server (high). */
+ USHORT ServerTimeZone;/*Time zone of server (minutes from UTC) */
+ UCHAR SecurityBlobLength;/*Length of SecurityBlob */
+
+ USHORT bcount; /*Count of data bytes */
+ /*UCHAR GUID[16]; A globally unique identifier assigned to the */
+ /* server; present only when */
+ /* CAP_EXTENDED_SECURITY is on in the */
+ /* Capabilities field. */
+ UCHAR SecurityBlob[SecurityBlobLength]; /*Opaque Security Blob associated with the */
+ /* security package if CAP_EXTENDED_SECURITY is */
+ /* on in the Capabilities field; else challenge */
+ /* for CIFS challenge/response authentication. */
+ fstring OemDomainName; /*The name of the domain (in OEM chars); not */
+ /* present if CAP_EXTENDED_SECURITY is on in the */
+ /* Capabilities field */
+} R_NEGPROT_17;
+
+
+typedef struct {
+ uint8 wcount;
+ union ctr[wcount] {
+ case 17 R_NEGPROT_17 r17;
+ }
+} R_NEGPROT;
+
+typedef struct {
+ uint8 wcount;
+ uint16 vwv[wcount];
+ uint16 bcount;
+ uint8 none[bcount];
+} Q_TDIS;
+
+typedef struct {
+ uint8 wcount;
+ uint16 vwv[wcount];
+ uint16 bcount;
+ uint8 none[bcount];
+} R_TDIS;
+
+typedef struct {
+ ANDX_INFO andx;
+ uint16 bcount;
+ uint8 none[bcount];
+} R_ULOGOFF_ANDX_2;
+
+typedef struct {
+ uint8 wcount;
+ union ctr[wcount] {
+ case 2 R_ULOGOFF_ANDX_2 q2;
+ }
+} R_ULOGOFF_ANDX;
+
+typedef struct {
+ ANDX_INFO andx;
+ uint16 bcount;
+ uint8 none[bcount];
+} Q_ULOGOFF_ANDX_2;
+
+typedef struct {
+ uint8 wcount;
+ union ctr[wcount] {
+ case 2 Q_ULOGOFF_ANDX_2 q2;
+ }
+} Q_ULOGOFF_ANDX;
+
+typedef struct {
+ ANDX_INFO andx;
+ uint16 bufsize;
+ uint16 max_mpx;
+ uint16 vc;
+ ULONG sess_key;
+ uint16 pwlen;
+ ULONG reserved;
+
+ uint16 bcount;
+ uint8 password[pwlen];
+ fstring domain;
+ fstring os;
+ fstring server;
+
+} Q_SESSION_SETUP_ANDX_10;
+
+typedef struct {
+ ANDX_INFO andx;
+ uint16 bufsize;
+ uint16 max_mpx;
+ uint16 vc;
+ ULONG sess_key;
+ uint16 pwlen;
+ uint16 upwlen;
+ ULONG capabilities;
+ ULONG reserved;
+
+ uint16 bcount;
+ uint8 password[pwlen];
+ uint8 upassword[upwlen];
+ fstring user;
+ fstring domain;
+ fstring os;
+ fstring server;
+
+} Q_SESSION_SETUP_ANDX_13;
+
+typedef struct _Q_SESSION_SETUP_ANDX {
+ uint8 wcount;
+ union ctr[wcount] {
+ case 10 Q_SESSION_SETUP_ANDX_10 q10;
+ case 13 Q_SESSION_SETUP_ANDX_13 q13;
+ }
+} Q_SESSION_SETUP_ANDX;
+
+typedef struct {
+ ANDX_INFO andx;
+ uint16 vwv2;
+ uint16 passlen;
+ uint16 bcount;
+ uint8 password[passlen];
+ fstring path;
+ fstring device;
+} Q_TCON_ANDX_4;
+
+typedef struct _Q_TCON_ANDX {
+ uint8 wcount;
+ union ctr[wcount] {
+ case 4 Q_TCON_ANDX_4 q4;
+ }
+} Q_TCON_ANDX;
+
+typedef struct {
+ ANDX_INFO andx;
+ uint16 vwv2;
+ uint16 bcount;
+ fstring share;
+} R_TCON_ANDX_3;
+
+typedef struct _R_TCON_ANDX {
+ uint8 wcount;
+ union ctr[wcount] {
+ case 3 R_TCON_ANDX_3 q3;
+ }
+} R_TCON_ANDX;
+
+typedef struct {
+ ANDX_INFO andx;
+ uint16 action;
+
+ uint16 count;
+ fstring os;
+ fstring server;
+ fstring domain;
+} R_SESSION_SETUP_ANDX_10;
+
+typedef struct _R_SESSION_SETUP_ANDX {
+ uint8 wcount;
+ union ctr[wcount] {
+ case 3 R_SESSION_SETUP_ANDX_10 r3;
+ }
+} R_SESSION_SETUP_ANDX;
+
+
+typedef struct _R_CLOSE {
+ uint8 wcount;
+ uint16 count;
+ uint8 none[count];
+
+} R_CLOSE;
+
+typedef struct _Q_CLOSE {
+ uint8 wcount;
+ uint16 fnum;
+ uint32 vwv1;
+
+ uint16 count;
+ uint8 none[count];
+
+} Q_CLOSE;
+
+typedef struct {
+ uint16 dsize;
+ uint16 bsizehi;
+ uint16 bsizelo;
+ uint16 avail;
+ uint16 vwv4;
+
+ uint16 bcount;
+ uint8 none[bcount];
+
+} R_DSKATTR_5;
+
+typedef struct {
+ uint8 wcount;
+ union ctr[wcount] {
+ case 5 R_DSKATTR_5 r5;
+ }
+} R_DSKATTR;
+
+typedef struct {
+ uint16 count;
+ uint8 none[count];
+
+} Q_DSKATTR_0;
+
+typedef struct _Q_DSKATTR {
+ uint8 wcount;
+ union ctr[wcount] {
+ case 0 Q_DSKATTR_0 q1;
+ }
+
+} Q_DSKATTR;
+
+typedef struct {
+ uint16 bcount;
+ uint8 protocols[bcount];
+
+} R_UNLINK_0;
+
+typedef struct {
+ uint8 wcount;
+ union ctr[wcount] {
+ case 0 R_UNLINK_0 r0;
+ }
+} R_UNLINK;
+
+typedef struct {
+ uint16 dirtype;
+
+ uint16 count;
+ uint8 fname[count];
+
+} Q_UNLINK_1;
+
+typedef struct _Q_UNLINK {
+ uint8 wcount;
+ union ctr[wcount] {
+ case 1 Q_UNLINK_1 q1;
+ }
+
+} Q_UNLINK;
+
+typedef struct _R_OPEN_ANDX{
+ uint8 wcount;
+ ANDX_INFO andx;
+ uint16 fnum;
+ uint16 fmode;
+ uint32 mtime;
+ uint32 size;
+ uint16 rmode;
+ uint16 vwv9;
+ uint16 vwv10;
+ uint16 smb_action;
+ uint16 vwv12;
+ uint16 vwv13;
+ uint16 vwv14;
+
+ uint16 count;
+ uint8 none[count];
+
+} R_OPEN_ANDX;
+
+typedef struct _Q_OPEN_ANDX{
+ uint8 wcount;
+ ANDX_INFO andx;
+ uint16 fnum;
+ uint16 fmode;
+ uint32 mtime;
+ uint32 size;
+ uint16 rmode;
+ uint16 vwv9;
+ uint16 vwv10;
+ uint16 smb_action;
+ uint16 vwv12;
+ uint16 vwv13;
+ uint16 vwv14;
+
+ uint16 count;
+ uint8 fname[count];
+
+} Q_OPEN_ANDX;
+
+typedef struct _R_READ_ANDX {
+ uint8 wcount;
+ ANDX_INFO andx;
+ uint16 vwv2;
+ uint16 vwv3;
+ uint16 vwv4;
+ uint16 nread;
+ uint16 offset;
+ uint16 vwv7;
+ uint16 vwv8;
+ uint16 vwv9;
+ uint16 vwv10;
+ uint16 vwv11;
+
+ uint16 count;
+ uint8 data[count];
+
+} R_READ_ANDX;
+
+typedef struct _Q_READ_ANDX_10 {
+ ANDX_INFO andx;
+ uint16 fnum;
+ uint32 startpos;
+ uint16 smb_maxcnt;
+ uint16 smb_mincnt;
+ uint16 vwv7;
+ uint16 vwv8;
+ uint16 vwv9;
+
+ uint16 count;
+ uint8 none[count];
+
+} Q_READ_ANDX_10;
+
+typedef struct _Q_READ_ANDX_12 {
+ ANDX_INFO andx;
+ uint16 fnum;
+ uint32 startpos;
+ uint16 smb_maxcnt;
+ uint16 smb_mincnt;
+ uint16 vwv7;
+ uint16 vwv8;
+ uint16 vwv9;
+ uint32 startposhi;
+
+ uint16 count;
+ uint8 none[count];
+
+} Q_READ_ANDX_12;
+
+typedef struct _Q_READ_ANDX {
+ uint8 wcount;
+ union ctr[wcount] {
+ case 10 Q_READ_ANDX_10 q10;
+ case 12 Q_READ_ANDX_12 q12;
+ }
+} Q_READ_ANDX;
+
+typedef struct _R_WRITE_ANDX {
+ uint8 wcount;
+ ANDX_INFO andx;
+ uint16 nwritten;
+ uint16 vwv3;
+ uint16 vwv4;
+ uint16 vwv5;
+
+ uint16 count;
+ uint8 none[count];
+
+} R_WRITE_ANDX;
+
+typedef struct _Q_WRITE_ANDX_12 {
+ ANDX_INFO andx;
+ uint16 fnum;
+ uint32 startpos;
+ uint16 vwv5;
+ uint16 vwv6;
+ uint16 write_through;
+ uint16 vwv8;
+ uint16 vwv9;
+ uint16 numtowrite;
+ uint16 smb_doff;
+
+ uint16 count;
+ uint8 data[count];
+
+} Q_WRITE_ANDX_12;
+
+typedef struct _Q_WRITE_ANDX_14 {
+ ANDX_INFO andx;
+ uint16 fnum;
+ uint32 startpos;
+ uint16 vwv5;
+ uint16 vwv6;
+ uint16 write_through;
+ uint16 vwv8;
+ uint16 vwv9;
+ uint16 numtowrite;
+ uint16 smb_doff;
+ uint32 startposhi;
+
+ uint16 count;
+ uint8 data[count];
+
+} Q_WRITE_ANDX_14;
+
+typedef struct _Q_WRITE_ANDX {
+ uint8 wcount;
+ union ctr[wcount] {
+ case 12 Q_WRITE_ANDX_12 q12;
+ case 14 Q_WRITE_ANDX_14 q14;
+ }
+} Q_WRITE_ANDX;
+
+typedef struct _Q_NT_CREATE_ANDX{
+ uint8 wcount;
+ ANDX_INFO andx;
+ uint8 reserved;
+ uint16 name_len;
+ ULONG flags;
+ ULONG rootfid;
+ ULONG access;
+ hyper allocsize;
+ ULONG attribs;
+ ULONG sharing;
+ ULONG creat_disp;
+ ULONG impersonation;
+ uint8 sec_flags;
+
+ uint16 count;
+ uint8 name[name_len];
+
+} Q_NT_CREATE_ANDX;
+
+typedef struct {
+ uint8 wcount;
+ uint8 oplock_level;
+ uint16 fid;
+ ULONG action;
+ TIME create_time;
+ TIME write_time;
+ TIME change_time;
+ ULONG ext_attribs;
+ hyper allocsize;
+ hyper size;
+ uint16 type;
+ uint16 state;
+ uint8 directory;
+
+ uint16 count;
+
+} R_NT_CREATE_ANDX;
+
+typedef struct _R_SMB {
+ ULONG nbhdr;
+ ULONG smbhdr;
+ uint8 com;
+ uint8 rcls;
+ uint8 reh;
+ uint16 err;
+ uint8 flg;
+ uint8 flg2;
+ uint8 reb[13];
+ uint16 tid;
+ uint16 pid;
+ uint16 uid;
+ uint16 mid;
+ union ctr[com] {
+ case 4 R_CLOSE r4;
+ case 6 R_UNLINK r6;
+ case 45 R_OPEN_ANDX r45;
+ case 46 R_READ_ANDX r46;
+ case 47 R_WRITE_ANDX r47;
+ case 113 R_TDIS r113;
+ case 114 R_NEGPROT r114;
+ case 115 R_SESSION_SETUP_ANDX r115;
+ case 117 R_TCON_ANDX q117;
+ case 128 R_DSKATTR r128;
+ }
+} R_SMB;
+
+typedef struct _Q_SMB {
+ ULONG nbhdr;
+ ULONG smbhdr;
+ uint8 com;
+ uint8 rcls;
+ uint8 reh;
+ uint16 err;
+ uint8 flg;
+ uint8 flg2;
+ uint8 reb[13];
+ uint16 tid;
+ uint16 pid;
+ uint16 uid;
+ uint16 mid;
+ union ctr[com] {
+ case 4 Q_CLOSE q4;
+ case 6 Q_UNLINK q6;
+ case 45 Q_OPEN_ANDX q45;
+ case 46 Q_READ_ANDX q46;
+ case 47 Q_WRITE_ANDX q47;
+ case 113 Q_TDIS q113;
+ case 114 Q_NEGPROT q114;
+ case 115 Q_SESSION_SETUP_ANDX q115;
+ case 117 Q_TCON_ANDX q117;
+ case 128 Q_DSKATTR q128;
+ }
+} Q_SMB;
+
diff --git a/source/aparser/parsefn.awk b/source/aparser/parsefn.awk
index 45c41d770b1..bff4521ba63 100644
--- a/source/aparser/parsefn.awk
+++ b/source/aparser/parsefn.awk
@@ -6,17 +6,33 @@ function elem_name(v, elem)
}
function parse_array(f, v, elnum, flags,
- LOCAL, type, elem)
+ LOCAL, type, elem, array_len)
{
type = elements[elnum, "type"];
elem = elements[elnum, "elem"];
+ array_len = elements[elnum, "array_len"];
v["ELEM"] = elem_name(v, elem);
v["TYPE"] = type;
v["FLAGS"] = flags;
- v["ARRAY_LEN"] = elements[elnum, "array_len"];
+ v["ARRAY_LEN"] = array_len;
- if (type == "wchar") {
- print_template(f, "prs_wstring.tpl", v);
+ if (array_len=="*") {
+ print_template(f,"prs_array_remainder.tpl", v);
+ return;
+ }
+
+ if (type == "wchar" || type == "uint16") {
+ if (match(array_len,"[0-9]") == 1) {
+ print_template(f, "prs_wstring_fixed.tpl", v);
+ } else {
+ print_template(f, "prs_wstring.tpl", v);
+ }
+ } else if (type == "uint8") {
+ if (match(array_len,"[0-9]") == 1) {
+ print_template(f, "prs_uint8s_fixed.tpl", v);
+ } else {
+ print_template(f, "prs_uint8s.tpl", v);
+ }
} else {
print_template(f, "prs_array.tpl", v);
}
diff --git a/source/aparser/parser.c b/source/aparser/parser.c
index 0e5f29b2bc5..289cf95c7bb 100644
--- a/source/aparser/parser.c
+++ b/source/aparser/parser.c
@@ -171,6 +171,8 @@ BOOL prs_align(prs_struct *ps, int align)
{
uint32 mod = ps->data_offset & (align-1);
+ return True;
+
if (align != 0 && mod != 0) {
uint32 extra_space = (align - mod);
if(!prs_grow(ps, extra_space))
@@ -320,6 +322,69 @@ BOOL io_pointer(char *desc, prs_struct *ps, int depth, void **p, unsigned flags)
return True;
}
+/*******************************************************************
+ Stream a null-terminated string.
+ ********************************************************************/
+BOOL io_fstring(char *name, prs_struct *ps, int depth, fstring *str, unsigned flags)
+{
+ char *q;
+ uint8 *start;
+ int i;
+ int len = sizeof(fstring)-1;
+
+ if (!(flags & PARSE_SCALARS)) return True;
+
+ if (MARSHALLING(ps)) {
+ len = MIN(len, strlen(*str));
+ }
+
+ start = (uint8*)q;
+
+ for(i = 0; i < len; i++) {
+ q = prs_mem_get(ps, 1);
+ if (q == NULL)
+ return False;
+
+ RW_CVAL(ps->io, q, (*str)[i],0);
+ if ((*str)[i] == 0)
+ break;
+ ps->data_offset++;
+ }
+
+ /* The terminating null. */
+ (*str)[i] = '\0';
+
+ if (MARSHALLING(ps)) {
+ RW_CVAL(ps->io, q, (*str)[i], 0);
+ }
+
+ ps->data_offset++;
+
+ DEBUG(5,("%s %s: %s\n", tab_depth(depth), name, *str));
+ return True;
+}
+
+/******************************************************************
+ do IO on a byte array
+ ********************************************************************/
+BOOL io_uint8s(char *name, prs_struct *ps, int depth, uint8 *data8s, int len, unsigned flags)
+{
+ char *q;
+
+ if (!(flags & PARSE_SCALARS)) return True;
+
+ if (!prs_align(ps, 2)) return False;
+
+ q = prs_mem_get(ps, len * sizeof(uint8));
+ if (q == NULL) return False;
+
+ DBG_RW_PCVAL(True, name, depth, ps->data_offset, ps->io, q, data8s, len)
+ ps->data_offset += (len * sizeof(uint8));
+
+ return True;
+}
+
+
/******************************************************************
do IO on a unicode array
********************************************************************/
@@ -351,3 +416,13 @@ BOOL io_alloc(char *name, prs_struct *ps, void **ptr, unsigned size)
return False;
}
+/******************************************************************
+realloc some memory for a parse structure
+ ********************************************************************/
+BOOL io_realloc(char *name, prs_struct *ps, void **ptr, unsigned size)
+{
+ (*ptr) = (void *)Realloc(*ptr, size);
+ if (*ptr) return True;
+ return False;
+}
+
diff --git a/source/aparser/parser.h b/source/aparser/parser.h
index 52d1b839414..51234d3dea0 100644
--- a/source/aparser/parser.h
+++ b/source/aparser/parser.h
@@ -28,11 +28,20 @@ typedef unsigned short uint16;
typedef unsigned short wchar;
typedef unsigned uint32;
+#ifndef _PSTRING
+
+#define PSTRING_LEN 1024
+#define FSTRING_LEN 128
+
+typedef char pstring[PSTRING_LEN];
+typedef char fstring[FSTRING_LEN];
+
+#define _PSTRING
+
+#endif
#define False 0
#define True 1
-typedef char pstring[1024];
-
/* zero a structure given a pointer to the structure */
#define ZERO_STRUCTP(x) { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); }
@@ -68,5 +77,7 @@ BOOL io_uint32(char *name, prs_struct *ps, int depth, uint32 *data32, unsigned f
BOOL io_uint16(char *name, prs_struct *ps, int depth, uint16 *data16, unsigned flags);
BOOL io_uint8(char *name, prs_struct *ps, int depth, uint8 *data8, unsigned flags);
BOOL io_pointer(char *desc, prs_struct *ps, int depth, void **p, unsigned flags);
+BOOL io_fstring(char *name, prs_struct *ps, int depth, fstring *str, unsigned flags);
BOOL io_wstring(char *name, prs_struct *ps, int depth, uint16 *data16s, int len, unsigned flags);
+BOOL io_uint8s(char *name, prs_struct *ps, int depth, uint8 *data8s, int len, unsigned flags);
diff --git a/source/aparser/templates/prs_array_remainder.tpl b/source/aparser/templates/prs_array_remainder.tpl
new file mode 100644
index 00000000000..80c5d8b9af7
--- /dev/null
+++ b/source/aparser/templates/prs_array_remainder.tpl
@@ -0,0 +1,7 @@
+ {
+ int i;
+ for (i=0;ps->data_offset < ps->buffer_size;i++) {
+ if (!io_alloc("@ELEM@", ps, (void **)&il->@ELEM@, sizeof(*(il->@ELEM@))*(i+1))) goto fail;
+ if (!io_@TYPE@("@ELEM@...", ps, depth+1, &il->@ELEM@[i], @FLAGS@)) goto fail;
+ }
+ }
diff --git a/source/aparser/templates/prs_array_remainder.tpl~ b/source/aparser/templates/prs_array_remainder.tpl~
new file mode 100644
index 00000000000..8050903f06a
--- /dev/null
+++ b/source/aparser/templates/prs_array_remainder.tpl~
@@ -0,0 +1,7 @@
+ {
+ int i;
+ for (i=0;ps->data_offset < ps->buffer_size;i++) {
+ if (!io_alloc("@ELEM@", ps, (void **)&il->@ELEM@, sizeof(*(il->@ELEM@))*(i+1)) goto fail;
+ if (!io_@TYPE@("@ELEM@...", ps, depth+1, &il->@ELEM@[i], @FLAGS@)) goto fail;
+ }
+ }
diff --git a/source/aparser/templates/prs_uint8s.tpl b/source/aparser/templates/prs_uint8s.tpl
new file mode 100644
index 00000000000..cfc4bab1d27
--- /dev/null
+++ b/source/aparser/templates/prs_uint8s.tpl
@@ -0,0 +1,2 @@
+ if (!io_alloc("@ELEM@", ps, (void **)&il->@ELEM@, sizeof(*(il->@ELEM@))*il->@ARRAY_LEN@)) goto fail;
+ if (!io_uint8s("@ELEM@", ps, depth+1, il->@ELEM@, il->@ARRAY_LEN@, @FLAGS@)) goto fail;
diff --git a/source/aparser/templates/prs_uint8s_fixed.tpl b/source/aparser/templates/prs_uint8s_fixed.tpl
new file mode 100644
index 00000000000..c8f55811309
--- /dev/null
+++ b/source/aparser/templates/prs_uint8s_fixed.tpl
@@ -0,0 +1,2 @@
+ if (!io_alloc("@ELEM@", ps, (void **)&il->@ELEM@, sizeof(*(il->@ELEM@))*@ARRAY_LEN@)) goto fail;
+ if (!io_uint8s("@ELEM@", ps, depth+1, il->@ELEM@, @ARRAY_LEN@, @FLAGS@)) goto fail;
diff --git a/source/aparser/templates/prs_wstring_fixed.tpl b/source/aparser/templates/prs_wstring_fixed.tpl
new file mode 100644
index 00000000000..bf2539b216a
--- /dev/null
+++ b/source/aparser/templates/prs_wstring_fixed.tpl
@@ -0,0 +1,2 @@
+ if (!io_alloc("@ELEM@", ps, (void **)&il->@ELEM@, sizeof(*(il->@ELEM@))*@ARRAY_LEN@)) goto fail;
+ if (!io_wstring("@ELEM@", ps, depth+1, il->@ELEM@, @ARRAY_LEN@, @FLAGS@)) goto fail;