/*
OpenChange MAPI implementation.
- Copyright (C) Julien Kerihuel 2005 - 2007.
+ Copyright (C) Julien Kerihuel 2005 - 2008.
Copyright (C) Jelmer Vernooij 2005.
This program is free software; you can redistribute it and/or modify
#include <param.h>
#include <credentials.h>
-#define ECDOCONNECT_FORMAT "/o=%s/ou=%s/cn=Recipients/cn=%s"
+/**
+ \file emsmdb.c
+
+ \brief EMSMDB stack functions
+ */
+
/**
- * Create a connection on the exchange_emsmdb pipe
+ \details Hash a string and returns a unsigned integer hash value
+
+ \param str the string to hash
+
+ \return a hash value greater than 0 on success, otherwise 0
+
+ \note This function is based on the hash algorithm from gdbm and
+ from Samba4 TDB code.
*/
+static unsigned int emsmdb_hash(const char *str)
+{
+ uint32_t value; /* Used to compute the hash value. */
+ uint32_t i; /* Used to cycle through random values. */
+ uint32_t len;
+
+ /* Sanity check */
+ if (!str) return 0;
+
+ len = strlen(str);
+
+ /* Set the initial value from the key size. */
+ for (value = 0x238F13AF * len, i = 0; i < len; i++)
+ value = (value + (str[i] << (i * 5 % 24)));
+
+ return (1103515243 * value + 12345);
+}
-struct emsmdb_context *emsmdb_connect(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *p, struct cli_credentials *cred)
+
+/**
+ \details Establishes a new Session Context with the server on the
+ exchange_emsmdb pipe
+
+ \param mem_ctx pointer to the memory context
+ \param session pointer to the MAPI session context
+ \param p pointer to the DCERPC pipe
+ \param cred pointer to the user credentials
+
+ \return an allocated emsmdb_context on success, otherwise NULL
+ */
+struct emsmdb_context *emsmdb_connect(TALLOC_CTX *mem_ctx,
+ struct mapi_session *session,
+ struct dcerpc_pipe *p,
+ struct cli_credentials *cred)
{
struct EcDoConnect r;
- NTSTATUS status;
struct emsmdb_context *ret;
- mapi_ctx_t *mapi_ctx;
+ NTSTATUS status;
+ enum MAPISTATUS retval;
+ uint32_t pullTimeStamp = 0;
- mapi_ctx = global_mapi_ctx;
- if (mapi_ctx == 0) return NULL;
+ /* Sanity Checks */
+ if (!session) return NULL;
+ if (!p) return NULL;
+ if (!cred) return NULL;
ret = talloc_zero(mem_ctx, struct emsmdb_context);
ret->rpc_connection = p;
ret->cache_requests = talloc(mem_ctx, struct EcDoRpc_MAPI_REQ *);
- r.in.name = mapi_ctx->session->profile->mailbox;
- r.in.unknown1[0] = 0x0;
- r.in.unknown1[1] = 0x1eeebaac;
- r.in.unknown1[2] = 0x0;
- r.in.code_page = mapi_ctx->session->profile->codepage;
- r.in.input_locale.language = mapi_ctx->session->profile->language;
- r.in.input_locale.method = mapi_ctx->session->profile->method;
- r.in.unknown2 = 0xffffffff;
- r.in.unknown3 = 0x1;
- r.in.emsmdb_client_version[0] = 0x000a;
- r.in.emsmdb_client_version[1] = 0x0000;
- r.in.emsmdb_client_version[2] = 0x1013;
-
- r.in.alloc_space = talloc(mem_ctx, uint32_t);
- *r.in.alloc_space = 0;
-
- r.out.unknown4[0] = (uint32_t)talloc(mem_ctx, uint32_t);
- r.out.unknown4[1] = (uint32_t)talloc(mem_ctx, uint32_t);
- r.out.unknown4[2] = (uint32_t)talloc(mem_ctx, uint32_t);
- r.out.session_nb = talloc(mem_ctx, uint16_t);
- r.out.alloc_space = talloc(mem_ctx, uint32_t);
+ r.in.szUserDN = session->profile->mailbox;
+ r.in.ulFlags = 0x00000000;
+ r.in.ulConMod = emsmdb_hash(r.in.szUserDN);
+ r.in.cbLimit = 0x00000000;
+ r.in.ulCpid = session->profile->codepage;
+ r.in.ulLcidString = session->profile->language;
+ r.in.ulLcidSort = session->profile->method;
+ r.in.ulIcxrLink = 0xFFFFFFFF;
+ r.in.usFCanConvertCodePages = 0x1;
+ r.in.rgwClientVersion[0] = 0x000c;
+ r.in.rgwClientVersion[1] = 0x183e;
+ r.in.rgwClientVersion[2] = 0x03e8;
+ r.in.pullTimeStamp = &pullTimeStamp;
+
r.out.handle = &ret->handle;
+ r.out.pcmsPollsMax = &ret->info.pcmsPollsMax;
+ r.out.pcRetry = &ret->info.pcRetry;
+ r.out.pcmsRetryDelay = &ret->info.pcmsRetryDelay;
+ r.out.picxr = &ret->info.picxr;
+ r.out.rgwServerVersion[0] = ret->info.rgwServerVersion[0];
+ r.out.rgwServerVersion[1] = ret->info.rgwServerVersion[1];
+ r.out.rgwServerVersion[2] = ret->info.rgwServerVersion[2];
+ r.out.pullTimeStamp = &pullTimeStamp;
status = dcerpc_EcDoConnect(p, mem_ctx, &r);
-
- if (!MAPI_STATUS_IS_OK(NT_STATUS_V(status))) {
- mapi_errstr("EcDoConnect", r.out.result);
+ retval = r.out.result;
+ if (!NT_STATUS_IS_OK(status) || retval) {
+ mapi_errstr("EcDoConnect", retval);
return NULL;
}
- ret->info.username = talloc_strdup(mem_ctx, r.out.user);
- ret->info.mailbox = talloc_strdup(mem_ctx, r.out.org_group);
- ret->info.store_version[0] = r.out.store_version[0];
- ret->info.store_version[1] = r.out.store_version[1];
- ret->info.store_version[2] = r.out.store_version[2];
-
- DEBUG(3, ("emsmdb_connect\n"));
- DEBUG(3, ("\t\t user = %s\n", r.out.user));
- DEBUG(3, ("\t\t organization = %s\n", r.out.org_group));
+ ret->info.szDisplayName = talloc_strdup(mem_ctx, r.out.szDisplayName);
+ ret->info.szDNPrefix = talloc_strdup(mem_ctx, r.out.szDNPrefix);
ret->cred = cred;
ret->max_data = 0xFFF0;
return ret;
}
+
/**
- * Destructor
- */
+ \details Destructor for the EMSMDB context. Call the EcDoDisconnect
+ function.
+
+ \param data generic pointer to data with mapi_provider information
+ \return MAPI_E_SUCCESS on success, otherwise -1
+ */
int emsmdb_disconnect_dtor(void *data)
{
- NTSTATUS status;
struct mapi_provider *provider = (struct mapi_provider *)data;
struct emsmdb_context *emsmdb_ctx;
emsmdb_ctx = (struct emsmdb_context *)provider->ctx;
- status = emsmdb_disconnect(provider->ctx);
-
- return 0;
+ return emsmdb_disconnect(provider->ctx);
}
+
/**
- * Close the connection on the initialized exchange_emsmdb pipe
- */
+ \details Destroy the EMSMDB context handle
-NTSTATUS emsmdb_disconnect(struct emsmdb_context *emsmdb)
+ \param emsmdb_ctx pointer to the EMSMDB context
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+enum MAPISTATUS emsmdb_disconnect(struct emsmdb_context *emsmdb_ctx)
{
NTSTATUS status;
+ enum MAPISTATUS retval;
struct EcDoDisconnect r;
- r.in.handle = r.out.handle = &emsmdb->handle;
+ /* Sanity Checks */
+ OPENCHANGE_RETVAL_IF(!emsmdb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
- status = dcerpc_EcDoDisconnect(emsmdb->rpc_connection, emsmdb, &r);
- if (!MAPI_STATUS_IS_OK(NT_STATUS_V(status))) {
- mapi_errstr("EcDoDisconnect", r.out.result);
- return status;
- }
+ r.in.handle = r.out.handle = &emsmdb_ctx->handle;
+
+ status = dcerpc_EcDoDisconnect(emsmdb_ctx->rpc_connection, emsmdb_ctx, &r);
+ retval = r.out.result;
+ OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, NULL);
+ OPENCHANGE_RETVAL_IF(retval, retval, NULL);
- return NT_STATUS_OK;
+ return MAPI_E_SUCCESS;
}
+
/**
- * Send a null MAPI packet.
- * Useful to keep connection up or force notifications
- */
+ \details Send an empty MAPI packet - useful to keep connection up
+ or force notifications.
-_PUBLIC_ NTSTATUS emsmdb_transaction_null(struct emsmdb_context *emsmdb, struct mapi_response **res)
+ \param emsmdb_ctx pointer to the EMSMDB connection context
+ \param res pointer on pointer to a MAPI response structure
+
+ \return NT_STATUS_OK on success, otherwise NT status error
+ */
+_PUBLIC_ NTSTATUS emsmdb_transaction_null(struct emsmdb_context *emsmdb_ctx,
+ struct mapi_response **res)
{
struct EcDoRpc r;
struct mapi_request *mapi_request;
NTSTATUS status;
uint16_t *length;
- mapi_request = talloc_zero(emsmdb->mem_ctx, struct mapi_request);
- mapi_response = talloc_zero(emsmdb->mem_ctx, struct mapi_response);
+ /* Sanity checks */
+ if(!emsmdb_ctx) return NT_STATUS_INVALID_PARAMETER;
+ if (!res) return NT_STATUS_INVALID_PARAMETER;
+
+ mapi_request = talloc_zero(emsmdb_ctx->mem_ctx, struct mapi_request);
+ mapi_response = talloc_zero(emsmdb_ctx->mem_ctx, struct mapi_response);
r.in.mapi_request = mapi_request;
r.in.mapi_request->mapi_len = 2;
r.in.mapi_request->length = 2;
- r.in.handle = r.out.handle = &emsmdb->handle;
- r.in.size = emsmdb->max_data;
+ r.in.handle = r.out.handle = &emsmdb_ctx->handle;
+ r.in.size = emsmdb_ctx->max_data;
r.in.offset = 0x0;
- r.in.max_data = emsmdb->max_data;
- length = talloc_zero(emsmdb->mem_ctx, uint16_t);
+ r.in.max_data = emsmdb_ctx->max_data;
+ length = talloc_zero(emsmdb_ctx->mem_ctx, uint16_t);
*length = r.in.mapi_request->mapi_len;
r.in.length = r.out.length = length;
r.out.mapi_response = mapi_response;
- status = dcerpc_EcDoRpc(emsmdb->rpc_connection, emsmdb->mem_ctx, &r);
-
+ status = dcerpc_EcDoRpc(emsmdb_ctx->rpc_connection, emsmdb_ctx->mem_ctx, &r);
if (!MAPI_STATUS_IS_OK(NT_STATUS_V(status))) {
return status;
}
return status;
}
-NTSTATUS emsmdb_transaction(struct emsmdb_context *emsmdb, struct mapi_request *req, struct mapi_response **repl)
+
+/**
+ \details Make a EMSMDB transaction.
+
+ \param emsmdb_ctx pointer to the EMSMDB connection context
+ \param req pointer to the MAPI request to send
+ \param repl pointer on pointer to the MAPI reply returned by the
+ server
+
+ \return NT_STATUS_OK on success, otherwise NT status error
+ */
+_PUBLIC_ NTSTATUS emsmdb_transaction(struct emsmdb_context *emsmdb_ctx,
+ struct mapi_request *req,
+ struct mapi_response **repl)
{
struct EcDoRpc r;
struct mapi_response *mapi_response;
uint8_t i = 0;
start:
- r.in.handle = r.out.handle = &emsmdb->handle;
- r.in.size = emsmdb->max_data;
+ r.in.handle = r.out.handle = &emsmdb_ctx->handle;
+ r.in.size = emsmdb_ctx->max_data;
r.in.offset = 0x0;
- mapi_response = talloc_zero(emsmdb->mem_ctx, struct mapi_response);
+ mapi_response = talloc_zero(emsmdb_ctx->mem_ctx, struct mapi_response);
r.out.mapi_response = mapi_response;
/* process cached data */
- if (emsmdb->cache_count) {
- multi_req = talloc_array(emsmdb->mem_ctx, struct EcDoRpc_MAPI_REQ, emsmdb->cache_count + 2);
- for (i = 0; i < emsmdb->cache_count; i++) {
- multi_req[i] = *emsmdb->cache_requests[i];
+ if (emsmdb_ctx->cache_count) {
+ multi_req = talloc_array(emsmdb_ctx->mem_ctx, struct EcDoRpc_MAPI_REQ, emsmdb_ctx->cache_count + 2);
+ for (i = 0; i < emsmdb_ctx->cache_count; i++) {
+ multi_req[i] = *emsmdb_ctx->cache_requests[i];
}
multi_req[i] = req->mapi_req[0];
req->mapi_req = multi_req;
}
- req->mapi_req = talloc_realloc(emsmdb->mem_ctx, req->mapi_req, struct EcDoRpc_MAPI_REQ, emsmdb->cache_count + 2);
+ req->mapi_req = talloc_realloc(emsmdb_ctx->mem_ctx, req->mapi_req, struct EcDoRpc_MAPI_REQ, emsmdb_ctx->cache_count + 2);
req->mapi_req[i+1].opnum = 0;
r.in.mapi_request = req;
- r.in.mapi_request->mapi_len += emsmdb->cache_size;
- r.in.mapi_request->length += emsmdb->cache_size;
- length = talloc_zero(emsmdb->mem_ctx, uint16_t);
+ r.in.mapi_request->mapi_len += emsmdb_ctx->cache_size;
+ r.in.mapi_request->length += emsmdb_ctx->cache_size;
+ length = talloc_zero(emsmdb_ctx->mem_ctx, uint16_t);
*length = r.in.mapi_request->mapi_len;
r.in.length = r.out.length = length;
- r.in.max_data = (*length >= 0x4000) ? 0x7FFF : emsmdb->max_data;
+ r.in.max_data = (*length >= 0x4000) ? 0x7FFF : emsmdb_ctx->max_data;
- status = dcerpc_EcDoRpc(emsmdb->rpc_connection, emsmdb->mem_ctx, &r);
-
- if (!MAPI_STATUS_IS_OK(NT_STATUS_V(status))) {
- if (emsmdb->setup == false) {
+ status = dcerpc_EcDoRpc(emsmdb_ctx->rpc_connection, emsmdb_ctx->mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (emsmdb_ctx->setup == false) {
errno = 0;
- emsmdb->max_data = 0x7FFF;
- emsmdb->setup = true;
+ emsmdb_ctx->max_data = 0x7FFF;
+ emsmdb_ctx->setup = true;
goto start;
} else {
return status;
}
} else {
- emsmdb->setup = true;
+ emsmdb_ctx->setup = true;
}
- emsmdb->cache_size = emsmdb->cache_count = 0;
+ emsmdb_ctx->cache_size = emsmdb_ctx->cache_count = 0;
*repl = r.out.mapi_response;
return status;
}
+
/**
- * initialize notify context structure and bind a local udp port for
- * notifications
+ \details Initialize the notify context structure and bind a local
+ UDP port to receive notifications from the server
+
+ \param mem_ctx pointer to the memory context
+
+ \return an allocated mapi_notify_ctx structure on success,
+ otherwise NULL
*/
struct mapi_notify_ctx *emsmdb_bind_notification(TALLOC_CTX *mem_ctx)
{
const char *ipaddr = NULL;
uint32_t try = 0;
+ /* Sanity Checks */
if (!global_mapi_ctx) return NULL;
if (!global_mapi_ctx->session) return NULL;
if (!global_mapi_ctx->session->profile) return NULL;
load_interfaces(mem_ctx, lp_interfaces(global_mapi_ctx->lp_ctx), &ifaces);
ipaddr = iface_best_ip(ifaces, global_mapi_ctx->session->profile->server);
- if (!ipaddr) return NULL;
+ if (!ipaddr) {
+ talloc_free(notify_ctx->notifications);
+ talloc_free(notify_ctx);
+ return NULL;
+ }
notify_ctx->addr = talloc_zero(mem_ctx, struct sockaddr);
notify_ctx->addr->sa_family = AF_INET;
((struct sockaddr_in *)(notify_ctx->addr))->sin_addr.s_addr = inet_addr(ipaddr);
notify_ctx->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (notify_ctx->fd == -1) {
+ talloc_free(notify_ctx->notifications);
+ talloc_free(notify_ctx->addr);
+ talloc_free(notify_ctx);
return NULL;
}
errno = 0;
goto retry;
}
+
+ talloc_free(notify_ctx->notifications);
+ talloc_free(notify_ctx->addr);
+ talloc_free(notify_ctx);
return NULL;
}
return notify_ctx;
}
+
/**
- * Register for notifications on a Exchange server
+ \details Register for notifications on the server
+
+ \param notifkey The opaque client-generated context data
+ \param ulEventMask Notification flags. Exchange completely ignores
+ this value and it should be set to 0
+
+ \return NTSTATUS_OK on success, otherwise NT status error
*/
-NTSTATUS emsmdb_register_notification(struct NOTIFKEY *notifkey, uint32_t ulEventMask)
+NTSTATUS emsmdb_register_notification(struct NOTIFKEY *notifkey,
+ uint16_t ulEventMask)
{
struct EcRRegisterPushNotification request;
NTSTATUS status;
- struct emsmdb_context *emsmdb;
+ enum MAPISTATUS retval;
+ TALLOC_CTX *mem_ctx;
+ struct emsmdb_context *emsmdb_ctx;
struct mapi_session *session;
struct mapi_notify_ctx *notify_ctx;
struct policy_handle handle;
+ uint32_t hNotification = 0;
- if (!global_mapi_ctx) return NT_STATUS_UNSUCCESSFUL;
- if (!global_mapi_ctx->session) return NT_STATUS_UNSUCCESSFUL;
- if (!global_mapi_ctx->session->emsmdb) return NT_STATUS_UNSUCCESSFUL;
- if (!global_mapi_ctx->session->emsmdb->ctx) return NT_STATUS_UNSUCCESSFUL;
+ /* Sanity Checks*/
+ if (!global_mapi_ctx) return NT_STATUS_INVALID_PARAMETER;
+ if (!global_mapi_ctx->session) return NT_STATUS_INVALID_PARAMETER;
+ if (!global_mapi_ctx->session->emsmdb) return NT_STATUS_INVALID_PARAMETER;
+ if (!global_mapi_ctx->session->emsmdb->ctx) return NT_STATUS_INVALID_PARAMETER;
+ if (!notifkey) return NT_STATUS_INVALID_PARAMETER;
session = (struct mapi_session *)global_mapi_ctx->session;
- emsmdb = (struct emsmdb_context *)session->emsmdb->ctx;
+ emsmdb_ctx = (struct emsmdb_context *)session->emsmdb->ctx;
notify_ctx = (struct mapi_notify_ctx *)session->notify_ctx;
+ mem_ctx = talloc_named(NULL, 0, "emsmdb_register_notification");
- /* in */
- request.in.handle = &emsmdb->handle;
+ request.in.handle = &emsmdb_ctx->handle;
request.in.ulEventMask = ulEventMask;
-
- request.in.notifkey = talloc_array(emsmdb->mem_ctx, uint8_t, request.in.notif_len);
- memcpy(request.in.notifkey, notifkey->ab, request.in.notif_len);
- request.in.notif_len = notifkey->cb;
-
- request.in.unknown2 = 0xffffffff;
-
- request.in.sockaddr = talloc_array(emsmdb->mem_ctx, uint8_t, sizeof (struct sockaddr));
+ request.in.cbContext = notifkey->cb;
+ request.in.rgbContext = talloc_array(mem_ctx, uint8_t, request.in.cbContext);
+ memcpy(request.in.rgbContext, notifkey->ab, request.in.cbContext);
+ request.in.grbitAdviseBits = 0xffffffff;
+ request.in.rgCallbackAddress = talloc_array(mem_ctx, uint8_t, sizeof (struct sockaddr));
/* cp address family and length */
- request.in.sockaddr[0] = (notify_ctx->addr->sa_family & 0xFF);
- request.in.sockaddr[1] = (notify_ctx->addr->sa_family & 0xFF00) >> 8;
- memcpy(&request.in.sockaddr[2], notify_ctx->addr->sa_data, 14);
- request.in.sockaddr_len = sizeof (struct sockaddr);
+ request.in.rgCallbackAddress[0] = (notify_ctx->addr->sa_family & 0xFF);
+ request.in.rgCallbackAddress[1] = (notify_ctx->addr->sa_family & 0xFF00) >> 8;
+ memcpy(&request.in.rgCallbackAddress[2], notify_ctx->addr->sa_data, 14);
+ request.in.cbCallbackAddress = sizeof (struct sockaddr);
- /* out */
request.out.handle = &handle;
- request.out.retval = talloc_zero(emsmdb->mem_ctx, uint32_t);
+ request.out.hNotification = &hNotification;
- status = dcerpc_EcRRegisterPushNotification(emsmdb->rpc_connection, emsmdb->mem_ctx, &request);
- if (!MAPI_STATUS_IS_OK(NT_STATUS_V(status))) {
+ status = dcerpc_EcRRegisterPushNotification(emsmdb_ctx->rpc_connection, emsmdb_ctx->mem_ctx, &request);
+ retval = request.out.result;
+ if (!NT_STATUS_IS_OK(status) || retval) {
+ talloc_free(mem_ctx);
return status;
}
- if (request.out.result != MAPI_E_SUCCESS) {
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- if (request.out.retval && *request.out.retval != MAPI_E_SUCCESS) {
- return NT_STATUS_UNSUCCESSFUL;
- }
+ talloc_free(mem_ctx);
- return NT_STATUS_OK;
+ return status;
}
/**
- * Retrieve the emsmdb server info structure
+ \details Retrieves the EMSMDB context server information structure
+
+ \param session pointer to the MAPI session context
+
+ \return the server info structure on success, otherwise NULL
*/
-_PUBLIC_ struct emsmdb_info *emsmdb_get_info(void)
+_PUBLIC_ struct emsmdb_info *emsmdb_get_info(struct mapi_session *session)
{
- if (!global_mapi_ctx || !global_mapi_ctx->session->emsmdb->ctx) {
+ if (!global_mapi_ctx || !session->emsmdb->ctx) {
return NULL;
}
- return &((struct emsmdb_context *)global_mapi_ctx->session->emsmdb->ctx)->info;
+ return &((struct emsmdb_context *)session->emsmdb->ctx)->info;
}
-const void *pull_emsmdb_property(TALLOC_CTX *mem_ctx, uint32_t *offset, enum MAPITAGS tag, DATA_BLOB *data)
+
+/**
+ \details Retrieves a property value from a DATA blob
+
+ \param mem_ctx pointer to the memory context
+ \param lp_ctx pointer to the loadparm context
+ \param offset pointer on pointer to the current offset
+ \param tag the property tag which value is to be retrieved
+ \param data pointer to the data
+
+ \return pointer on constant generic data on success, otherwise NULL
+ */
+const void *pull_emsmdb_property(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx,
+ uint32_t *offset,
+ enum MAPITAGS tag,
+ DATA_BLOB *data)
{
- struct ndr_pull *ndr;
- const char *pt_string8;
- const char *pt_unicode;
- uint16_t *pt_i2;
- uint64_t *pt_i8;
- uint32_t *pt_long;
- uint8_t *pt_boolean;
- struct FILETIME *pt_filetime;
- struct GUID *pt_clsid;
- struct SBinary_short pt_binary;
- struct SBinary *sbin;
+ struct ndr_pull *ndr;
+ const char *pt_string8;
+ const char *pt_unicode;
+ uint16_t *pt_i2;
+ uint64_t *pt_i8;
+ uint32_t *pt_long;
+ uint8_t *pt_boolean;
+ struct FILETIME *pt_filetime;
+ struct GUID *pt_clsid;
+ struct SBinary_short pt_binary;
+ struct Binary_r *sbin;
+ struct mapi_SLPSTRArray pt_slpstr;
+ struct StringArray_r *slpstr;
+ struct mapi_MV_LONG_STRUCT pt_MVl;
+ struct LongArray_r *MVl;
+ struct mapi_SBinaryArray pt_MVbin;
+ struct BinaryArray_r *MVbin;
+ uint32_t i;
ndr = talloc_zero(mem_ctx, struct ndr_pull);
ndr->offset = *offset;
ndr->data = data->data;
ndr->data_size = data->length;
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
- ndr->iconv_convenience = smb_iconv_convenience_init(mem_ctx, "CP850", "UTF8", true);
+ ndr->iconv_convenience = lp_iconv_convenience(lp_ctx);
switch(tag & 0xFFFF) {
case PT_I2:
pt_i2 = talloc_zero(mem_ctx, uint16_t);
ndr_pull_uint16(ndr, NDR_SCALARS, pt_i2);
*offset = ndr->offset;
+ talloc_free(ndr);
return (void *) pt_i2;
case PT_ERROR:
case PT_LONG:
pt_long = talloc_zero(mem_ctx, uint32_t);
ndr_pull_uint32(ndr, NDR_SCALARS, pt_long);
*offset = ndr->offset;
+ talloc_free(ndr);
return (void *) pt_long;
case PT_BOOLEAN:
pt_boolean = talloc_zero(mem_ctx, uint8_t);
ndr_pull_uint8(ndr, NDR_SCALARS, pt_boolean);
*offset = ndr->offset;
+ talloc_free(ndr);
return (void *) pt_boolean;
case PT_I8:
pt_i8 = talloc_zero(mem_ctx, uint64_t);
ndr_pull_hyper(ndr, NDR_SCALARS, pt_i8);
*offset = ndr->offset;
+ talloc_free(ndr);
return (void *) pt_i8;
case PT_UNICODE:
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
ndr_pull_string(ndr, NDR_SCALARS, &pt_unicode);
*offset = ndr->offset;
+ talloc_free(ndr);
return (const void *) pt_unicode;
case PT_STRING8:
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM);
ndr_pull_string(ndr, NDR_SCALARS, &pt_string8);
*offset = ndr->offset;
+ talloc_free(ndr);
return (const void *) pt_string8;
case PT_SYSTIME:
pt_filetime = talloc_zero(mem_ctx, struct FILETIME);
ndr_pull_hyper(ndr, NDR_SCALARS, (uint64_t *) pt_filetime);
*offset = ndr->offset;
- return (void*) pt_filetime;
+ talloc_free(ndr);
+ return (void *) pt_filetime;
case PT_CLSID:
pt_clsid = talloc_zero(mem_ctx, struct GUID);
ndr_pull_GUID(ndr, NDR_SCALARS, pt_clsid);
*offset = ndr->offset;
+ talloc_free(ndr);
return (void *) pt_clsid;
case 0xFB:
case PT_BINARY:
ndr_pull_SBinary_short(ndr, NDR_SCALARS, &pt_binary);
*offset = ndr->offset;
- sbin = talloc_zero(mem_ctx, struct SBinary);
+ sbin = talloc_zero(mem_ctx, struct Binary_r);
sbin->cb = pt_binary.cb;
- sbin->lpb = pt_binary.lpb;
+ sbin->lpb = talloc_memdup(sbin, pt_binary.lpb, pt_binary.cb);
+ talloc_free(ndr);
return (void *) sbin;
+ case PT_MV_LONG:
+ ndr_pull_mapi_MV_LONG_STRUCT(ndr, NDR_SCALARS, &pt_MVl);
+ *offset = ndr->offset;
+ MVl = talloc_zero(mem_ctx, struct LongArray_r);
+ MVl->cValues = pt_MVl.cValues;
+ MVl->lpl = talloc_array(mem_ctx, uint32_t, pt_MVl.cValues);
+ for (i = 0; i < MVl->cValues; i++) {
+ MVl->lpl[i] = pt_MVl.lpl[i];
+ }
+ talloc_free(ndr);
+ return (const void *) MVl;
+ case PT_MV_STRING8:
+ ndr_pull_mapi_SLPSTRArray(ndr, NDR_SCALARS, &pt_slpstr);
+ *offset = ndr->offset;
+ slpstr = talloc_zero(mem_ctx, struct StringArray_r);
+ slpstr->cValues = pt_slpstr.cValues;
+ slpstr->lppszA = talloc_array(mem_ctx, const char *, pt_slpstr.cValues);
+ for (i = 0; i < slpstr->cValues; i++) {
+ slpstr->lppszA[i] = talloc_strdup(mem_ctx, pt_slpstr.strings[i].lppszA);
+ }
+ talloc_free(ndr);
+ return (const void *) slpstr;
+ case PT_MV_BINARY:
+ ndr_pull_mapi_SBinaryArray(ndr, NDR_SCALARS, &pt_MVbin);
+ *offset = ndr->offset;
+ MVbin = talloc_zero(mem_ctx, struct BinaryArray_r);
+ MVbin->cValues = pt_MVbin.cValues;
+ MVbin->lpbin = talloc_array(mem_ctx, struct Binary_r, pt_MVbin.cValues);
+ for (i = 0; i < MVbin->cValues; i++) {
+ MVbin->lpbin[i].cb = pt_MVbin.bin[i].cb;
+ MVbin->lpbin[i].lpb = talloc_size(mem_ctx, MVbin->lpbin[i].cb);
+ memcpy(MVbin->lpbin[i].lpb, pt_MVbin.bin[i].lpb, MVbin->lpbin[i].cb);
+ }
+ talloc_free(ndr);
+ return (const void *) MVbin;
default:
return NULL;
}
}
+
+/**
+ \details Get a SPropValue array from a DATA blob
+
+ \param mem_ctx pointer to the memory context
+ \param lp_ctx pointer to the loadparm context
+ \param content pointer to the DATA blob content
+ \param tags pointer to a list of property tags to lookup
+ \param propvals pointer on pointer to the returned SPropValues
+ \param cn_propvals pointer to the number of propvals
+ \param flag describes the type data
+
+ \return MAPI_E_SUCCESS on success
+ */
enum MAPISTATUS emsmdb_get_SPropValue(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx,
DATA_BLOB *content,
struct SPropTagArray *tags,
- struct SPropValue **propvals, uint32_t *cn_propvals,
- uint8_t layout)
+ struct SPropValue **propvals,
+ uint32_t *cn_propvals,
+ uint8_t flag)
{
struct SPropValue *p_propval;
uint32_t i_propval;
i_propval = 0;
cn_tags = tags->cValues;
*cn_propvals = 0;
- *propvals = talloc_array(mem_ctx, struct SPropValue, cn_tags);
+ *propvals = talloc_array(mem_ctx, struct SPropValue, cn_tags + 1);
for (i_tag = 0; i_tag < cn_tags; i_tag++) {
- if (layout) {
+ if (flag) {
if (((uint8_t)(*(content->data + offset))) == PT_ERROR) {
tags->aulPropTag[i_tag] &= 0xFFFF0000;
tags->aulPropTag[i_tag] |= PT_ERROR;
offset += sizeof (uint8_t);
}
- data = pull_emsmdb_property(mem_ctx, &offset, tags->aulPropTag[i_tag], content);
+ data = pull_emsmdb_property(mem_ctx, lp_ctx, &offset, tags->aulPropTag[i_tag], content);
if (data) {
p_propval = &((*propvals)[i_propval]);
p_propval->ulPropTag = tags->aulPropTag[i_tag];
}
}
+ (*propvals)[i_propval].ulPropTag = 0x0;
*cn_propvals = i_propval;
return MAPI_E_SUCCESS;
}
-/* TODO: this doesn't yet handle the TypedPropertyValue and
- FlaggedPropertyValueWithTypeSpecified variants. */
-_PUBLIC_ void emsmdb_get_SRowSet(TALLOC_CTX *mem_ctx, struct SRowSet *rowset, struct SPropTagArray *proptags, DATA_BLOB *content)
+
+/**
+ \details Get a SRowSet from a DATA blob
+
+ \param mem_ctx pointer on the memory context
+ \param lp_ctx pointer on the loadparm context
+ \param rowset pointer on the returned SRowSe
+ \param proptags pointer on a list of property tags to lookup
+ \param content pointer on the DATA blob content
+
+ \return MAPI_E_SUCCESS on success
+
+ \note TODO: this doesn't yet handle the TypedPropertyValue and
+ FlaggedPropertyValueWithTypeSpecified variants
+ */
+_PUBLIC_ void emsmdb_get_SRowSet(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx,
+ struct SRowSet *rowset,
+ struct SPropTagArray *proptags,
+ DATA_BLOB *content)
{
struct SRow *rows;
struct SPropValue *lpProps;
/* Property Value is not present */
havePropertyValue = false;
break;
- case 0xa:
+ case PT_ERROR:
lpProps[prop].ulPropTag = proptags->aulPropTag[prop];
lpProps[prop].ulPropTag &= 0xFFFF0000;
- lpProps[prop].ulPropTag |= 0x000a;
+ lpProps[prop].ulPropTag |= PT_ERROR;
break;
default:
/* unknown FlaggedPropertyValue flag */
}
if (havePropertyValue) {
lpProps[prop].dwAlignPad = 0x0;
- data = pull_emsmdb_property(mem_ctx, &offset, lpProps[prop].ulPropTag, content);
+ data = pull_emsmdb_property(mem_ctx, lp_ctx, &offset, lpProps[prop].ulPropTag, content);
set_SPropValue(&lpProps[prop], data);
}
}
}
-void emsmdb_get_SRow(TALLOC_CTX *mem_ctx, struct SRow *aRow, struct SPropTagArray *proptags, uint16_t propcount, DATA_BLOB *content, uint8_t layout, uint8_t align)
+/**
+ \details Get a SRow from a DATA blob
+
+ \param mem_ctx pointer on the memory context
+ \param lp_ctx pointer on the loadparm context
+ \param aRow pointer on the returned SRow
+ \param proptags pointer on a list of property tags to lookup
+ \param propcount number of SPropValue entries in aRow
+ \param content pointer on the DATA blob content
+ \param flag the type data
+ \param align alignment pad
+
+ \return MAPI_E_SUCCESS on success
+
+ \note TODO: We shouldn't have any alignment pad here
+ */
+void emsmdb_get_SRow(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx,
+ struct SRow *aRow,
+ struct SPropTagArray *proptags,
+ uint16_t propcount,
+ DATA_BLOB *content,
+ uint8_t flag,
+ uint8_t align)
{
uint32_t i;
uint32_t offset = 0;
for (i = 0; i < propcount; i++) {
aulPropTag = proptags->aulPropTag[i];
- if (layout) {
+ if (flag) {
if (((uint8_t)(*(content->data + offset))) == PT_ERROR) {
aulPropTag &= 0xFFFF0000;
aulPropTag |= 0xA;
offset += align;
}
- data = pull_emsmdb_property(mem_ctx, &offset, aulPropTag, content);
+ data = pull_emsmdb_property(mem_ctx, lp_ctx, &offset, aulPropTag, content);
aRow->lpProps[i].ulPropTag = aulPropTag;
aRow->lpProps[i].dwAlignPad = 0x0;
set_SPropValue(&(aRow->lpProps[i]), data);