diff options
Diffstat (limited to 'librpc')
-rw-r--r-- | librpc/idl/cab.idl | 2 | ||||
-rw-r--r-- | librpc/ndr/ndr_cab.c | 49 | ||||
-rw-r--r-- | librpc/ndr/ndr_cab.h | 1 |
3 files changed, 51 insertions, 1 deletions
diff --git a/librpc/idl/cab.idl b/librpc/idl/cab.idl index af8dad24404..2174bce7334 100644 --- a/librpc/idl/cab.idl +++ b/librpc/idl/cab.idl @@ -111,7 +111,7 @@ import "misc.idl"; } CFFILE; typedef [public,flag(NDR_PAHEX|NDR_LITTLE_ENDIAN|NDR_NOALIGN)] struct { - uint32 csum; /* checksum of this CFDATA entry */ + [value(ndr_cab_generate_checksum(r))] uint32 csum; /* checksum of this CFDATA entry */ uint16 cbData; /* number of compressed bytes in this block */ uint16 cbUncomp; /* number of uncompressed bytes in this block */ #if 0 diff --git a/librpc/ndr/ndr_cab.c b/librpc/ndr/ndr_cab.c index 87c103a4901..611e378cb34 100644 --- a/librpc/ndr/ndr_cab.c +++ b/librpc/ndr/ndr_cab.c @@ -63,6 +63,55 @@ uint32_t ndr_count_cfdata(const struct cab_file *r) return count; } +static uint32_t ndr_cab_compute_checksum(uint8_t *data, uint32_t length, uint32_t seed) +{ + int num_ulong; + uint32_t checksum; + uint8_t *pb; + uint32_t ul; + + num_ulong = length / 4; + checksum = seed; + pb = data; + + while (num_ulong-- > 0) { + ul = *pb++; + ul |= (((uint32_t)(*pb++)) << 8); + ul |= (((uint32_t)(*pb++)) << 16); + ul |= (((uint32_t)(*pb++)) << 24); + + checksum ^= ul; + } + + ul = 0; + + switch (length % 4) { + case 3: + ul |= (((uint32_t)(*pb++)) << 16); + case 2: + ul |= (((uint32_t)(*pb++)) << 8); + case 1: + ul |= *pb++; + default: + break; + } + + checksum ^= ul; + + return checksum; +} + +uint32_t ndr_cab_generate_checksum(const struct CFDATA *r) +{ + uint32_t csumPartial; + + csumPartial = ndr_cab_compute_checksum(&r->ab[0], r->cbData, 0); + + return ndr_cab_compute_checksum((uint8_t *)discard_const(&r->cbData), + sizeof(r->cbData) + sizeof(r->cbUncomp), + csumPartial); +} + _PUBLIC_ enum ndr_err_code ndr_push_cab_file(struct ndr_push *ndr, int ndr_flags, const struct cab_file *r) { uint32_t cntr_cffolders_0; diff --git a/librpc/ndr/ndr_cab.h b/librpc/ndr/ndr_cab.h index 39b6bc9b483..59dbc991442 100644 --- a/librpc/ndr/ndr_cab.h +++ b/librpc/ndr/ndr_cab.h @@ -20,3 +20,4 @@ */ uint32_t ndr_count_cfdata(const struct cab_file *r); +uint32_t ndr_cab_generate_checksum(const struct CFDATA *r); |