summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--librpc/idl/cab.idl2
-rw-r--r--librpc/ndr/ndr_cab.c49
-rw-r--r--librpc/ndr/ndr_cab.h1
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);