2
OpenChange MAPI implementation.
4
Copyright (C) Julien Kerihuel 2005 - 2008.
5
Copyright (C) Jelmer Vernooij 2005.
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 3 of the License, or
10
(at your option) any later version.
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with this program. If not, see <http://www.gnu.org/licenses/>.
23
#include <libmapi/libmapi.h>
24
#include <libmapi/proto_private.h>
25
#include <gen_ndr/ndr_exchange.h>
26
#include <gen_ndr/ndr_exchange_c.h>
27
#include <gen_ndr/ndr_misc.h>
34
\brief EMSMDB stack functions
39
\details Hash a string and returns a unsigned integer hash value
41
\param str the string to hash
43
\return a hash value greater than 0 on success, otherwise 0
45
\note This function is based on the hash algorithm from gdbm and
48
static unsigned int emsmdb_hash(const char *str)
50
uint32_t value; /* Used to compute the hash value. */
51
uint32_t i; /* Used to cycle through random values. */
59
/* Set the initial value from the key size. */
60
for (value = 0x238F13AF * len, i = 0; i < len; i++)
61
value = (value + (str[i] << (i * 5 % 24)));
63
return (1103515243 * value + 12345);
68
\details Establishes a new Session Context with the server on the
71
\param parent_mem_ctx pointer to the memory context
72
\param session pointer to the MAPI session context
73
\param p pointer to the DCERPC pipe
74
\param cred pointer to the user credentials
75
\param return_value pointer on EcDoConnect MAPI return value
77
\return an allocated emsmdb_context on success, otherwise NULL
79
struct emsmdb_context *emsmdb_connect(TALLOC_CTX *parent_mem_ctx,
80
struct mapi_session *session,
81
struct dcerpc_pipe *p,
82
struct cli_credentials *cred,
87
struct emsmdb_context *ret;
89
enum MAPISTATUS retval;
90
uint32_t pullTimeStamp = 0;
93
if (!session) return NULL;
95
if (!cred) return NULL;
96
if (!return_value) return NULL;
98
mem_ctx = talloc_named(NULL, 0, "emsmdb_connect");
100
ret = talloc_zero(parent_mem_ctx, struct emsmdb_context);
101
ret->rpc_connection = p;
102
ret->mem_ctx = parent_mem_ctx;
104
ret->cache_requests = talloc(parent_mem_ctx, struct EcDoRpc_MAPI_REQ *);
105
ret->info.szDisplayName = NULL;
106
ret->info.szDNPrefix = NULL;
108
r.in.szUserDN = session->profile->mailbox;
109
r.in.ulFlags = 0x00000000;
110
r.in.ulConMod = emsmdb_hash(r.in.szUserDN);
111
r.in.cbLimit = 0x00000000;
112
r.in.ulCpid = session->profile->codepage;
113
r.in.ulLcidString = session->profile->language;
114
r.in.ulLcidSort = session->profile->method;
115
r.in.ulIcxrLink = 0xFFFFFFFF;
116
r.in.usFCanConvertCodePages = 0x1;
117
r.in.rgwClientVersion[0] = 0x000c;
118
r.in.rgwClientVersion[1] = 0x183e;
119
r.in.rgwClientVersion[2] = 0x03e8;
120
r.in.pullTimeStamp = &pullTimeStamp;
122
r.out.handle = &ret->handle;
123
r.out.pcmsPollsMax = &ret->info.pcmsPollsMax;
124
r.out.pcRetry = &ret->info.pcRetry;
125
r.out.pcmsRetryDelay = &ret->info.pcmsRetryDelay;
126
r.out.picxr = &ret->info.picxr;
127
r.out.pullTimeStamp = &pullTimeStamp;
129
status = dcerpc_EcDoConnect(p, mem_ctx, &r);
130
retval = r.out.result;
131
if (!NT_STATUS_IS_OK(status) || retval) {
132
*return_value = retval;
133
mapi_errstr("EcDoConnect", retval);
134
talloc_free(mem_ctx);
138
ret->info.szDisplayName = talloc_strdup(parent_mem_ctx, r.out.szDisplayName);
139
ret->info.szDNPrefix = talloc_strdup(parent_mem_ctx, r.out.szDNPrefix);
141
ret->info.rgwServerVersion[0] = r.out.rgwServerVersion[0];
142
ret->info.rgwServerVersion[1] = r.out.rgwServerVersion[1];
143
ret->info.rgwServerVersion[2] = r.out.rgwServerVersion[2];
146
ret->max_data = 0xFFF0;
149
talloc_free(mem_ctx);
156
\details Destructor for the EMSMDB context. Call the EcDoDisconnect
159
\param data generic pointer to data with mapi_provider information
161
\return MAPI_E_SUCCESS on success, otherwise -1
163
int emsmdb_disconnect_dtor(void *data)
165
struct mapi_provider *provider = (struct mapi_provider *)data;
166
struct emsmdb_context *emsmdb_ctx;
168
emsmdb_ctx = (struct emsmdb_context *)provider->ctx;
169
emsmdb_disconnect(provider->ctx);
171
talloc_free(emsmdb_ctx->cache_requests);
173
if (emsmdb_ctx->info.szDisplayName) {
174
talloc_free(emsmdb_ctx->info.szDisplayName);
177
if (emsmdb_ctx->info.szDNPrefix) {
178
talloc_free(emsmdb_ctx->info.szDNPrefix);
186
\details Destroy the EMSMDB context handle
188
\param emsmdb_ctx pointer to the EMSMDB context
190
\return MAPI_E_SUCCESS on success, otherwise MAPI error
192
enum MAPISTATUS emsmdb_disconnect(struct emsmdb_context *emsmdb_ctx)
195
enum MAPISTATUS retval;
196
struct EcDoDisconnect r;
199
OPENCHANGE_RETVAL_IF(!emsmdb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
201
r.in.handle = r.out.handle = &emsmdb_ctx->handle;
203
status = dcerpc_EcDoDisconnect(emsmdb_ctx->rpc_connection, emsmdb_ctx, &r);
204
retval = r.out.result;
205
OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, NULL);
206
OPENCHANGE_RETVAL_IF(retval, retval, NULL);
208
return MAPI_E_SUCCESS;
213
\details Send an empty MAPI packet - useful to keep connection up
214
or force notifications.
216
\param emsmdb_ctx pointer to the EMSMDB connection context
217
\param res pointer on pointer to a MAPI response structure
219
\return NT_STATUS_OK on success, otherwise NT status error
221
_PUBLIC_ NTSTATUS emsmdb_transaction_null(struct emsmdb_context *emsmdb_ctx,
222
struct mapi_response **res)
225
struct mapi_request *mapi_request;
226
struct mapi_response *mapi_response;
231
if(!emsmdb_ctx) return NT_STATUS_INVALID_PARAMETER;
232
if (!res) return NT_STATUS_INVALID_PARAMETER;
234
mapi_request = talloc_zero(emsmdb_ctx->mem_ctx, struct mapi_request);
235
mapi_response = talloc_zero(emsmdb_ctx->mem_ctx, struct mapi_response);
237
r.in.mapi_request = mapi_request;
238
r.in.mapi_request->mapi_len = 2;
239
r.in.mapi_request->length = 2;
241
r.in.handle = r.out.handle = &emsmdb_ctx->handle;
242
r.in.size = emsmdb_ctx->max_data;
244
r.in.max_data = emsmdb_ctx->max_data;
245
length = talloc_zero(emsmdb_ctx->mem_ctx, uint16_t);
246
*length = r.in.mapi_request->mapi_len;
247
r.in.length = r.out.length = length;
249
r.out.mapi_response = mapi_response;
251
status = dcerpc_EcDoRpc(emsmdb_ctx->rpc_connection, emsmdb_ctx->mem_ctx, &r);
252
if (!MAPI_STATUS_IS_OK(NT_STATUS_V(status))) {
256
*res = mapi_response;
262
static int mapi_response_destructor(void *data)
264
struct mapi_response *mapi_response = (struct mapi_response *)data;
266
if (!mapi_response) return 0;
268
if (mapi_response->mapi_repl) {
269
if (mapi_response->handles) {
270
talloc_free(mapi_response->handles);
273
if (!mapi_response->mapi_repl->error_code) {
274
talloc_free(mapi_response->mapi_repl);
283
\details Make a EMSMDB transaction.
285
\param emsmdb_ctx pointer to the EMSMDB connection context
286
\param mem_ctx pointer to the memory context
287
\param req pointer to the MAPI request to send
288
\param repl pointer on pointer to the MAPI reply returned by the
291
\return NT_STATUS_OK on success, otherwise NT status error
293
_PUBLIC_ NTSTATUS emsmdb_transaction(struct emsmdb_context *emsmdb_ctx,
295
struct mapi_request *req,
296
struct mapi_response **repl)
299
struct mapi_response *mapi_response;
302
struct EcDoRpc_MAPI_REQ *multi_req;
306
r.in.handle = r.out.handle = &emsmdb_ctx->handle;
307
r.in.size = emsmdb_ctx->max_data;
310
mapi_response = talloc_zero(emsmdb_ctx->mem_ctx, struct mapi_response);
311
mapi_response->mapi_repl = NULL;
312
mapi_response->handles = NULL;
313
talloc_set_destructor((void *)mapi_response, (int (*)(void *))mapi_response_destructor);
314
r.out.mapi_response = mapi_response;
316
/* process cached data */
317
if (emsmdb_ctx->cache_count) {
318
multi_req = talloc_array(mem_ctx, struct EcDoRpc_MAPI_REQ, emsmdb_ctx->cache_count + 2);
319
for (i = 0; i < emsmdb_ctx->cache_count; i++) {
320
multi_req[i] = *emsmdb_ctx->cache_requests[i];
322
multi_req[i] = req->mapi_req[0];
323
req->mapi_req = multi_req;
326
req->mapi_req = talloc_realloc(mem_ctx, req->mapi_req, struct EcDoRpc_MAPI_REQ, emsmdb_ctx->cache_count + 2);
327
req->mapi_req[i+1].opnum = 0;
329
r.in.mapi_request = req;
330
r.in.mapi_request->mapi_len += emsmdb_ctx->cache_size;
331
r.in.mapi_request->length += emsmdb_ctx->cache_size;
332
length = talloc_zero(mem_ctx, uint16_t);
333
*length = r.in.mapi_request->mapi_len;
334
r.in.length = r.out.length = length;
335
r.in.max_data = (*length >= 0x4000) ? 0x7FFF : emsmdb_ctx->max_data;
337
status = dcerpc_EcDoRpc(emsmdb_ctx->rpc_connection, mem_ctx, &r);
338
if (!NT_STATUS_IS_OK(status)) {
339
if (emsmdb_ctx->setup == false) {
341
emsmdb_ctx->max_data = 0x7FFF;
342
emsmdb_ctx->setup = true;
343
talloc_free(mapi_response);
346
talloc_free(mapi_response);
350
emsmdb_ctx->setup = true;
352
emsmdb_ctx->cache_size = emsmdb_ctx->cache_count = 0;
354
if (r.out.mapi_response->mapi_repl && r.out.mapi_response->mapi_repl->error_code) {
355
talloc_set_destructor((void *)mapi_response, NULL);
356
r.out.mapi_response->handles = NULL;
359
*repl = r.out.mapi_response;
366
\details Initialize the notify context structure and bind a local
367
UDP port to receive notifications from the server
369
\param mem_ctx pointer to the memory context
371
\return an allocated mapi_notify_ctx structure on success,
374
struct mapi_notify_ctx *emsmdb_bind_notification(TALLOC_CTX *mem_ctx)
376
struct interface *ifaces;
377
struct mapi_notify_ctx *notify_ctx = NULL;
378
unsigned short port = DFLT_NOTIF_PORT;
379
const char *ipaddr = NULL;
383
if (!global_mapi_ctx) return NULL;
384
if (!global_mapi_ctx->session) return NULL;
385
if (!global_mapi_ctx->session->profile) return NULL;
387
notify_ctx = talloc_zero(mem_ctx, struct mapi_notify_ctx);
389
notify_ctx->notifications = talloc_zero((TALLOC_CTX *)notify_ctx, struct notifications);
390
notify_ctx->notifications->prev = NULL;
391
notify_ctx->notifications->next = NULL;
393
load_interfaces(mem_ctx, lp_interfaces(global_mapi_ctx->lp_ctx), &ifaces);
394
ipaddr = iface_best_ip(ifaces, global_mapi_ctx->session->profile->server);
396
talloc_free(notify_ctx->notifications);
397
talloc_free(notify_ctx);
400
notify_ctx->addr = talloc_zero(mem_ctx, struct sockaddr);
401
notify_ctx->addr->sa_family = AF_INET;
402
((struct sockaddr_in *)(notify_ctx->addr))->sin_addr.s_addr = inet_addr(ipaddr);
405
((struct sockaddr_in *)(notify_ctx->addr))->sin_port = htons(port);
407
notify_ctx->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
408
if (notify_ctx->fd == -1) {
409
talloc_free(notify_ctx->notifications);
410
talloc_free(notify_ctx->addr);
411
talloc_free(notify_ctx);
415
fcntl(notify_ctx->fd, F_SETFL, O_NONBLOCK);
417
if (bind(notify_ctx->fd, notify_ctx->addr, sizeof(struct sockaddr)) == -1) {
418
shutdown(notify_ctx->fd, SHUT_RDWR);
419
close(notify_ctx->fd);
426
talloc_free(notify_ctx->notifications);
427
talloc_free(notify_ctx->addr);
428
talloc_free(notify_ctx);
437
\details Register for notifications on the server
439
\param session Pointer to the current MAPI session
440
\param notifkey The opaque client-generated context data
441
\param ulEventMask Notification flags. Exchange completely ignores
442
this value and it should be set to 0
444
\return NTSTATUS_OK on success, otherwise NT status error
446
NTSTATUS emsmdb_register_notification(struct mapi_session *session,
447
struct NOTIFKEY *notifkey,
448
uint16_t ulEventMask)
450
struct EcRRegisterPushNotification request;
452
enum MAPISTATUS retval;
454
struct emsmdb_context *emsmdb_ctx;
455
struct mapi_notify_ctx *notify_ctx;
456
struct policy_handle handle;
457
uint32_t hNotification = 0;
460
if (!global_mapi_ctx) return NT_STATUS_INVALID_PARAMETER;
461
if (!global_mapi_ctx->session) return NT_STATUS_INVALID_PARAMETER;
462
if (!global_mapi_ctx->session->emsmdb) return NT_STATUS_INVALID_PARAMETER;
463
if (!global_mapi_ctx->session->emsmdb->ctx) return NT_STATUS_INVALID_PARAMETER;
464
if (!notifkey) return NT_STATUS_INVALID_PARAMETER;
466
emsmdb_ctx = (struct emsmdb_context *)session->emsmdb->ctx;
467
notify_ctx = (struct mapi_notify_ctx *)session->notify_ctx;
468
mem_ctx = talloc_named(NULL, 0, "emsmdb_register_notification");
470
request.in.handle = &emsmdb_ctx->handle;
471
request.in.ulEventMask = ulEventMask;
472
request.in.cbContext = notifkey->cb;
473
request.in.rgbContext = talloc_array(mem_ctx, uint8_t, request.in.cbContext);
474
memcpy(request.in.rgbContext, notifkey->ab, request.in.cbContext);
475
request.in.grbitAdviseBits = 0xffffffff;
476
request.in.rgCallbackAddress = talloc_array(mem_ctx, uint8_t, sizeof (struct sockaddr));
477
/* cp address family and length */
478
request.in.rgCallbackAddress[0] = (notify_ctx->addr->sa_family & 0xFF);
479
request.in.rgCallbackAddress[1] = (notify_ctx->addr->sa_family & 0xFF00) >> 8;
480
memcpy(&request.in.rgCallbackAddress[2], notify_ctx->addr->sa_data, 14);
481
request.in.cbCallbackAddress = sizeof (struct sockaddr);
483
request.out.handle = &handle;
484
request.out.hNotification = &hNotification;
486
status = dcerpc_EcRRegisterPushNotification(emsmdb_ctx->rpc_connection, emsmdb_ctx->mem_ctx, &request);
487
retval = request.out.result;
488
if (!NT_STATUS_IS_OK(status) || retval) {
489
talloc_free(mem_ctx);
493
talloc_free(mem_ctx);
500
\details Retrieves the EMSMDB context server information structure
502
\param session pointer to the MAPI session context
504
\return the server info structure on success, otherwise NULL
506
_PUBLIC_ struct emsmdb_info *emsmdb_get_info(struct mapi_session *session)
508
if (!global_mapi_ctx || !session->emsmdb->ctx) {
512
return &((struct emsmdb_context *)session->emsmdb->ctx)->info;
517
\details Free property values retrieved with pull_emsmdb_property
519
\param lpProp pointer to SPropValue structure
520
\param data generic pointer to associated lpProp data
523
void free_emsmdb_property(struct SPropValue *lpProp, void *data)
528
switch (lpProp->ulPropTag & 0xFFFF) {
530
talloc_free((uint16_t *)data);
534
talloc_free((uint32_t *)data);
537
talloc_free((uint64_t *)data);
540
talloc_free((uint8_t *)data);
550
\details Retrieves a property value from a DATA blob
552
\param mem_ctx pointer to the memory context
553
\param lp_ctx pointer to the loadparm context
554
\param offset pointer on pointer to the current offset
555
\param tag the property tag which value is to be retrieved
556
\param data pointer to the data
558
\return pointer on constant generic data on success, otherwise NULL
560
const void *pull_emsmdb_property(TALLOC_CTX *mem_ctx,
561
struct loadparm_context *lp_ctx,
566
struct ndr_pull *ndr;
567
const char *pt_string8;
568
const char *pt_unicode;
574
struct FILETIME *pt_filetime;
575
struct GUID *pt_clsid;
576
struct SBinary_short pt_binary;
577
struct Binary_r *sbin;
578
struct mapi_SLPSTRArray pt_slpstr;
579
struct StringArray_r *slpstr;
580
struct mapi_MV_LONG_STRUCT pt_MVl;
581
struct LongArray_r *MVl;
582
struct mapi_SBinaryArray pt_MVbin;
583
struct BinaryArray_r *MVbin;
586
ndr = talloc_zero(mem_ctx, struct ndr_pull);
587
ndr->offset = *offset;
588
ndr->data = data->data;
589
ndr->data_size = data->length;
590
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
591
ndr->iconv_convenience = lp_iconv_convenience(lp_ctx);
593
switch(tag & 0xFFFF) {
595
pt_i2 = talloc_zero(mem_ctx, uint16_t);
596
ndr_pull_uint16(ndr, NDR_SCALARS, pt_i2);
597
*offset = ndr->offset;
599
return (const void *) pt_i2;
602
pt_long = talloc_zero(mem_ctx, uint32_t);
603
ndr_pull_uint32(ndr, NDR_SCALARS, pt_long);
604
*offset = ndr->offset;
606
return (const void *) pt_long;
608
pt_boolean = talloc_zero(mem_ctx, uint8_t);
609
ndr_pull_uint8(ndr, NDR_SCALARS, pt_boolean);
610
*offset = ndr->offset;
612
return (const void *) pt_boolean;
614
pt_i8 = talloc_zero(mem_ctx, uint64_t);
615
ndr_pull_hyper(ndr, NDR_SCALARS, pt_i8);
616
*offset = ndr->offset;
618
return (const void *) pt_i8;
620
pt_double = talloc_zero(mem_ctx, double);
621
ndr_pull_double(ndr, NDR_SCALARS, pt_double);
622
*offset = ndr->offset;
624
return (const void *) pt_double;
626
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
627
ndr_pull_string(ndr, NDR_SCALARS, &pt_unicode);
628
*offset = ndr->offset;
630
return (const void *) pt_unicode;
632
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM);
633
ndr_pull_string(ndr, NDR_SCALARS, &pt_string8);
634
*offset = ndr->offset;
636
return (const void *) pt_string8;
638
pt_filetime = talloc_zero(mem_ctx, struct FILETIME);
639
ndr_pull_hyper(ndr, NDR_SCALARS, (uint64_t *) pt_filetime);
640
*offset = ndr->offset;
642
return (const void *) pt_filetime;
644
pt_clsid = talloc_zero(mem_ctx, struct GUID);
645
ndr_pull_GUID(ndr, NDR_SCALARS, pt_clsid);
646
*offset = ndr->offset;
648
return (const void *) pt_clsid;
651
ndr_pull_SBinary_short(ndr, NDR_SCALARS, &pt_binary);
652
*offset = ndr->offset;
653
sbin = talloc_zero(mem_ctx, struct Binary_r);
654
sbin->cb = pt_binary.cb;
655
sbin->lpb = talloc_memdup(sbin, pt_binary.lpb, pt_binary.cb);
657
return (const void *) sbin;
659
ndr_pull_mapi_MV_LONG_STRUCT(ndr, NDR_SCALARS, &pt_MVl);
660
*offset = ndr->offset;
661
MVl = talloc_zero(mem_ctx, struct LongArray_r);
662
MVl->cValues = pt_MVl.cValues;
663
MVl->lpl = talloc_array(mem_ctx, uint32_t, pt_MVl.cValues);
664
for (i = 0; i < MVl->cValues; i++) {
665
MVl->lpl[i] = pt_MVl.lpl[i];
668
return (const void *) MVl;
670
ndr_pull_mapi_SLPSTRArray(ndr, NDR_SCALARS, &pt_slpstr);
671
*offset = ndr->offset;
672
slpstr = talloc_zero(mem_ctx, struct StringArray_r);
673
slpstr->cValues = pt_slpstr.cValues;
674
slpstr->lppszA = talloc_array(mem_ctx, const char *, pt_slpstr.cValues);
675
for (i = 0; i < slpstr->cValues; i++) {
676
slpstr->lppszA[i] = talloc_strdup(mem_ctx, pt_slpstr.strings[i].lppszA);
679
return (const void *) slpstr;
681
ndr_pull_mapi_SBinaryArray(ndr, NDR_SCALARS, &pt_MVbin);
682
*offset = ndr->offset;
683
MVbin = talloc_zero(mem_ctx, struct BinaryArray_r);
684
MVbin->cValues = pt_MVbin.cValues;
685
MVbin->lpbin = talloc_array(mem_ctx, struct Binary_r, pt_MVbin.cValues);
686
for (i = 0; i < MVbin->cValues; i++) {
687
MVbin->lpbin[i].cb = pt_MVbin.bin[i].cb;
688
MVbin->lpbin[i].lpb = talloc_size(mem_ctx, MVbin->lpbin[i].cb);
689
memcpy(MVbin->lpbin[i].lpb, pt_MVbin.bin[i].lpb, MVbin->lpbin[i].cb);
692
return (const void *) MVbin;
694
fprintf (stderr, "unhandled type case in pull_emsmdb_property(): 0x%x\n", (tag & 0xFFFF));
701
\details Get a SPropValue array from a DATA blob
703
\param mem_ctx pointer to the memory context
704
\param lp_ctx pointer to the loadparm context
705
\param content pointer to the DATA blob content
706
\param tags pointer to a list of property tags to lookup
707
\param propvals pointer on pointer to the returned SPropValues
708
\param cn_propvals pointer to the number of propvals
709
\param flag describes the type data
711
\return MAPI_E_SUCCESS on success
713
enum MAPISTATUS emsmdb_get_SPropValue(TALLOC_CTX *mem_ctx,
714
struct loadparm_context *lp_ctx,
716
struct SPropTagArray *tags,
717
struct SPropValue **propvals,
718
uint32_t *cn_propvals,
721
struct SPropValue *p_propval;
729
cn_tags = tags->cValues;
731
*propvals = talloc_array(mem_ctx, struct SPropValue, cn_tags + 1);
733
for (i_tag = 0; i_tag < cn_tags; i_tag++) {
735
if (((uint8_t)(*(content->data + offset))) == PT_ERROR) {
736
tags->aulPropTag[i_tag] &= 0xFFFF0000;
737
tags->aulPropTag[i_tag] |= PT_ERROR;
739
offset += sizeof (uint8_t);
742
data = pull_emsmdb_property(mem_ctx, lp_ctx, &offset, tags->aulPropTag[i_tag], content);
744
data = talloc_steal(*propvals, data);
745
p_propval = &((*propvals)[i_propval]);
746
p_propval->ulPropTag = tags->aulPropTag[i_tag];
747
p_propval->dwAlignPad = 0x0;
749
set_SPropValue(p_propval, data);
750
free_emsmdb_property(p_propval, (void *) data);
755
(*propvals)[i_propval].ulPropTag = 0x0;
756
*cn_propvals = i_propval;
757
return MAPI_E_SUCCESS;
762
\details Get a SRowSet from a DATA blob
764
\param mem_ctx pointer on the memory context
765
\param lp_ctx pointer on the loadparm context
766
\param rowset pointer on the returned SRowSe
767
\param proptags pointer on a list of property tags to lookup
768
\param content pointer on the DATA blob content
770
\return MAPI_E_SUCCESS on success
772
\note TODO: this doesn't yet handle the TypedPropertyValue and
773
FlaggedPropertyValueWithTypeSpecified variants
775
_PUBLIC_ void emsmdb_get_SRowSet(TALLOC_CTX *mem_ctx,
776
struct loadparm_context *lp_ctx,
777
struct SRowSet *rowset,
778
struct SPropTagArray *proptags,
782
struct SPropValue *lpProps;
788
bool is_FlaggedPropertyRow = false;
789
bool havePropertyValue;
792
/* caller allocated */
794
row_count = rowset->cRows;
796
for (idx = 0; idx < row_count; idx++) {
797
if (0x1 == *(content->data + offset)) {
798
is_FlaggedPropertyRow = true;
800
is_FlaggedPropertyRow = false;
804
lpProps = talloc_array(mem_ctx, struct SPropValue, proptags->cValues);
805
for (prop = 0; prop < proptags->cValues; prop++) {
806
havePropertyValue = true;
807
lpProps[prop].ulPropTag = proptags->aulPropTag[prop];
808
if (is_FlaggedPropertyRow) {
809
flag = (uint8_t)(*(content->data + offset));
810
++offset; /* advance offset for the flag */
813
/* Property Value is valid */
816
/* Property Value is not present */
817
havePropertyValue = false;
820
lpProps[prop].ulPropTag = proptags->aulPropTag[prop];
821
lpProps[prop].ulPropTag &= 0xFFFF0000;
822
lpProps[prop].ulPropTag |= PT_ERROR;
825
/* unknown FlaggedPropertyValue flag */
830
if (havePropertyValue) {
831
lpProps[prop].dwAlignPad = 0x0;
832
data = pull_emsmdb_property(mem_ctx, lp_ctx, &offset, lpProps[prop].ulPropTag, content);
833
talloc_steal(lpProps, data);
834
set_SPropValue(&lpProps[prop], data);
835
free_emsmdb_property(&lpProps[prop], (void *) data);
839
rows[idx].ulAdrEntryPad = 0;
840
rows[idx].cValues = proptags->cValues;
841
rows[idx].lpProps = lpProps;
847
\details Get a SRow from a DATA blob
849
\param mem_ctx pointer on the memory context
850
\param lp_ctx pointer on the loadparm context
851
\param aRow pointer on the returned SRow
852
\param proptags pointer on a list of property tags to lookup
853
\param propcount number of SPropValue entries in aRow
854
\param content pointer on the DATA blob content
855
\param flag the type data
856
\param align alignment pad
858
\return MAPI_E_SUCCESS on success
860
\note TODO: We shouldn't have any alignment pad here
862
void emsmdb_get_SRow(TALLOC_CTX *mem_ctx,
863
struct loadparm_context *lp_ctx,
865
struct SPropTagArray *proptags,
873
uint32_t aulPropTag = 0;
876
aRow->cValues = propcount;
877
aRow->lpProps = talloc_array(mem_ctx, struct SPropValue, propcount);
879
for (i = 0; i < propcount; i++) {
880
aulPropTag = proptags->aulPropTag[i];
882
if (((uint8_t)(*(content->data + offset))) == PT_ERROR) {
883
aulPropTag &= 0xFFFF0000;
889
data = pull_emsmdb_property(mem_ctx, lp_ctx, &offset, aulPropTag, content);
890
talloc_steal(aRow->lpProps, data);
891
aRow->lpProps[i].ulPropTag = aulPropTag;
892
aRow->lpProps[i].dwAlignPad = 0x0;
893
set_SPropValue(&(aRow->lpProps[i]), data);
894
free_emsmdb_property(&aRow->lpProps[i], (void *) data);