+static BOOL notify_change_record_identical(struct notify_change *c1,
+ struct notify_change *c2)
+{
+ /* Note this is deliberately case sensitive. */
+ if (c1->action == c2->action &&
+ strcmp(c1->name, c2->name) == 0) {
+ return True;
+ }
+ return False;
+}
+
+static BOOL notify_marshall_changes(int num_changes,
+ struct notify_change *changes,
+ prs_struct *ps)
+{
+ int i;
+ UNISTR uni_name;
+
+ for (i=0; i<num_changes; i++) {
+ struct notify_change *c;
+ size_t namelen;
+ uint32 u32_tmp; /* Temp arg to prs_uint32 to avoid
+ * signed/unsigned issues */
+
+ /* Coalesce any identical records. */
+ while (i+1 < num_changes &&
+ notify_change_record_identical(&changes[i],
+ &changes[i+1])) {
+ i++;
+ }
+
+ c = &changes[i];
+
+ namelen = convert_string_allocate(
+ NULL, CH_UNIX, CH_UTF16LE, c->name, strlen(c->name)+1,
+ &uni_name.buffer, True);
+ if ((namelen == -1) || (uni_name.buffer == NULL)) {
+ goto fail;
+ }
+
+ namelen -= 2; /* Dump NULL termination */
+
+ /*
+ * Offset to next entry, only if there is one
+ */
+
+ u32_tmp = (i == num_changes-1) ? 0 : namelen + 12;
+ if (!prs_uint32("offset", ps, 1, &u32_tmp)) goto fail;
+
+ u32_tmp = c->action;
+ if (!prs_uint32("action", ps, 1, &u32_tmp)) goto fail;
+
+ u32_tmp = namelen;
+ if (!prs_uint32("namelen", ps, 1, &u32_tmp)) goto fail;
+
+ if (!prs_unistr("name", ps, 1, &uni_name)) goto fail;
+
+ /*
+ * Not NULL terminated, decrease by the 2 UCS2 \0 chars
+ */
+ prs_set_offset(ps, prs_offset(ps)-2);
+
+ SAFE_FREE(uni_name.buffer);
+ }
+
+ return True;
+
+ fail:
+ SAFE_FREE(uni_name.buffer);
+ return False;
+}