2349b1e3de157a245a6eef46ed328377802882fe
[jelmer/openchange.git] / torture / mapi_namedprops.c
1 /*
2    OpenChange MAPI torture suite implementation.
3
4    Test Named properties and IMAPIProp associated functions
5
6    Copyright (C) Julien Kerihuel 2007.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <libmapi/libmapi.h>
23 #include <gen_ndr/ndr_exchange.h>
24 #include <param.h>
25 #include <credentials.h>
26 #include <torture/mapi_torture.h>
27 #include <torture.h>
28 #include <torture/torture_proto.h>
29 #include <samba/popt.h>
30
31 #define NAMEDPROP_NAME  "torture_namedprops"
32 #define NAMEDPROP_VALUE "Can you see me?"
33
34 bool torture_rpc_mapi_namedprops(struct torture_context *torture)
35 {
36         NTSTATUS                        status;
37         enum MAPISTATUS                 retval;
38         struct dcerpc_pipe              *p;
39         TALLOC_CTX                      *mem_ctx;
40         bool                            ret = true;
41         struct mapi_session             *session;
42         mapi_id_t                       id_folder;
43         mapi_object_t                   obj_store;
44         mapi_object_t                   obj_folder;
45         mapi_object_t                   obj_table;
46         mapi_object_t                   obj_message;
47         struct SRowSet                  SRowSet;
48         struct SPropTagArray            *SPropTagArray;
49         struct SPropValue               *propvals;
50         struct mapi_SPropValue_array    props_array;
51         uint32_t                        i;
52         uint32_t                        propID;
53         uint16_t                        count;
54         struct MAPINAMEID               *nameid;
55         uint16_t                        *propIDs;
56         uint32_t                        cn_propvals;
57
58         /* init torture */
59         mem_ctx = talloc_init("torture_rpc_mapi_namedprops");
60         status = torture_rpc_connection(torture, &p, &ndr_table_exchange_emsmdb);
61         if (!NT_STATUS_IS_OK(status)) {
62                 talloc_free(mem_ctx);
63                 return false;
64         }
65         
66         /* init mapi */
67         if ((session = torture_init_mapi(mem_ctx, torture->lp_ctx)) == NULL) return false;
68
69         /* OpenMsgStore */
70         mapi_object_init(&obj_store);
71         retval = OpenMsgStore(session, &obj_store);
72         if (retval != MAPI_E_SUCCESS) return false;
73
74         /* Retrieve the specified folder ID */
75         retval = GetDefaultFolder(&obj_store, &id_folder, olFolderInbox);
76         if (retval != MAPI_E_SUCCESS) return false;
77
78         /* Open the folder */
79         mapi_object_init(&obj_folder);
80         retval = OpenFolder(&obj_store, id_folder, &obj_folder);
81         if (retval != MAPI_E_SUCCESS) return false;
82
83         /* Retrieve the folder contents */
84         mapi_object_init(&obj_table);
85         retval = GetContentsTable(&obj_folder, &obj_table, 0, NULL);
86         if (retval != MAPI_E_SUCCESS) return false;
87
88         SPropTagArray = set_SPropTagArray(mem_ctx, 0x8,
89                                           PR_FID,
90                                           PR_MID,
91                                           PR_INST_ID,
92                                           PR_INSTANCE_NUM,
93                                           PR_SUBJECT,
94                                           PR_MESSAGE_CLASS,
95                                           PR_RULE_MSG_PROVIDER,
96                                           PR_RULE_MSG_NAME);
97         retval = SetColumns(&obj_table, SPropTagArray);
98         MAPIFreeBuffer(SPropTagArray);
99         if (retval != MAPI_E_SUCCESS) return false;
100
101         retval = QueryRows(&obj_table, 0x32, TBL_ADVANCE, &SRowSet);
102         if (retval != MAPI_E_SUCCESS) return false;
103
104         /* We just need to open the first message for this test */
105         if (SRowSet.cRows == 0) {
106                 printf("No messages in Mailbox\n");
107                 talloc_free(mem_ctx);
108                 return false;
109         }
110
111         mapi_object_init(&obj_message);
112         retval = OpenMessage(&obj_folder,
113                              SRowSet.aRow[0].lpProps[0].value.d,
114                              SRowSet.aRow[0].lpProps[1].value.d,
115                              &obj_message, MAPI_MODIFY|MAPI_CREATE);
116         if (retval != MAPI_E_SUCCESS) return false;
117
118         retval = GetPropsAll(&obj_message, &props_array);
119         if (retval != MAPI_E_SUCCESS) return false;
120
121         /* loop through properties, search for named properties
122          * (0x8000-0xFFFE range) and call GetNamesFromIDs 
123          */
124         printf("\n\n1. GetNamesFromIDs\n");
125         for (i = 0; i < props_array.cValues; i++) {
126                 propID = props_array.lpProps[i].ulPropTag >> 16;
127                 if (propID >= 0x8000 && propID <= 0xFFFE) {
128                         propID = props_array.lpProps[i].ulPropTag;
129                         propID = (propID & 0xFFFF0000) | PT_NULL;
130                         nameid = talloc_zero(mem_ctx, struct MAPINAMEID);
131                         retval = GetNamesFromIDs(&obj_message, propID, &count, &nameid);
132                         if (retval != MAPI_E_SUCCESS) return false;
133                         switch (nameid->ulKind) {
134                         case MNID_ID:
135                                 printf("\t0x%.8x mapped to 0x%.4x\n", 
136                                        propID | (props_array.lpProps[i].ulPropTag & 0xFFFF), nameid->kind.lid);
137                                 break;
138                         case MNID_STRING:
139                                 printf("\t0x%.8x mapped to %s\n",
140                                        propID, nameid->kind.lpwstr.Name);
141                                 break;
142                         }
143                         talloc_free(nameid);
144                 }
145         }
146
147         /*
148          * Retrieve all the named properties for the current object
149          * This function seems to be the only one accepting 0 for
150          * input ulPropTag and returning the whole set of named properties
151          */
152         printf("\n\n2. QueryNamedProperties\n");
153         nameid = talloc_zero(mem_ctx, struct MAPINAMEID);
154         propIDs = talloc_zero(mem_ctx, uint16_t);
155         retval = QueryNamedProperties(&obj_message, 0, NULL, &count, &propIDs, &nameid);
156         mapi_errstr("QueryNamedProperties", GetLastError());
157         if (retval != MAPI_E_SUCCESS) return false;
158
159         for (i = 0; i < count; i++) {
160                 char    *guid;
161
162                 printf("0x%.4x:\n", propIDs[i]);
163
164                 guid = GUID_string(mem_ctx, &nameid[i].lpguid);
165                 printf("\tguid: %s\n", guid);
166                 talloc_free(guid);
167
168                 switch (nameid[i].ulKind) {
169                 case MNID_ID:
170                         printf("\tmapped to 0x%.4x\n", nameid[i].kind.lid);
171                         break;
172                 case MNID_STRING:
173                         printf("\tmapped to %s\n", nameid[i].kind.lpwstr.Name);
174                         break;
175                 }               
176         }
177         talloc_free(propIDs);
178
179         /*
180          * finally call GetIDsFromNames with the Names retrieved in
181          * the previous call
182          */
183         printf("\n\n3. GetIDsFromNames\n");
184         for (i = 0; i < count; i++) {
185                 SPropTagArray = talloc_zero(mem_ctx, struct SPropTagArray);
186                 retval = GetIDsFromNames(&obj_folder, 1, &nameid[i], 0, &SPropTagArray);
187                 switch (nameid[i].ulKind) {
188                 case MNID_ID:
189                         printf("0x%.4x mapped to ", nameid[i].kind.lid);
190                         break;
191                 case MNID_STRING:
192                         printf("%s mapped to ", nameid[i].kind.lpwstr.Name);
193                         break;
194                 }       
195                 mapidump_SPropTagArray(SPropTagArray);
196                 talloc_free(SPropTagArray);
197         }
198
199         talloc_free(nameid);
200
201         /*
202          * Try to create a named property
203          */
204         {
205           struct GUID guid;
206
207           printf("\n\n4. GetIDsFromNames (Create named property)\n");
208           GUID_from_string(PS_INTERNET_HEADERS, &guid);
209           nameid = talloc_zero(mem_ctx, struct MAPINAMEID);
210           SPropTagArray = talloc_zero(mem_ctx, struct SPropTagArray);
211
212           nameid[0].lpguid = guid;
213           nameid[0].ulKind = MNID_STRING;
214           nameid[0].kind.lpwstr.Name = NAMEDPROP_NAME;
215           nameid[0].kind.lpwstr.NameSize = strlen(NAMEDPROP_NAME) * 2 + 2;
216           retval = GetIDsFromNames(&obj_folder, 1, &nameid[0], MAPI_CREATE, &SPropTagArray);
217           if (retval != MAPI_E_SUCCESS) return false;
218           mapi_errstr("GetIDsFromNames", GetLastError());
219
220           printf("%s mapped to 0x%.8x\n", NAMEDPROP_NAME, SPropTagArray->aulPropTag[0]);
221           propID = SPropTagArray->aulPropTag[0] | PT_STRING8;
222
223           talloc_free(nameid);
224           talloc_free(SPropTagArray);
225         }
226
227         /*
228          * Assign its value with SetProps and save changes
229          */
230         {
231                 struct SPropValue       props[1];
232                 const char              *testval = NAMEDPROP_VALUE;
233
234                 printf("\n\n5. Assigning %s to %s\n", NAMEDPROP_VALUE, NAMEDPROP_NAME);
235                 
236                 set_SPropValue_proptag(&props[0], propID, (const void *)testval);
237                 retval = SetProps(&obj_message, props, 1);
238                 if (retval != MAPI_E_SUCCESS) return false;
239                 mapi_errstr("SetProps", GetLastError());
240                 
241                 retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
242                 mapi_errstr("SaveChangesMessage", GetLastError());
243                 if (retval != MAPI_E_SUCCESS) return false;
244         }
245
246         printf("\n\n6. GetNamesFromIDs (Fetch torture_namedprops property)\n");
247         propID = (propID & 0xFFFF0000)| PT_NULL;
248         retval = GetNamesFromIDs(&obj_message, propID, &count, &nameid);
249         mapi_errstr("GetNamesFromIDs", GetLastError());
250         if (retval != MAPI_E_SUCCESS) return false;
251         switch (nameid->ulKind) {
252         case MNID_ID:
253                 printf("\t0x%.8x mapped to 0x%.4x\n", 
254                        propID | (props_array.lpProps[i].ulPropTag & 0xFFFF), nameid->kind.lid);
255                 break;
256         case MNID_STRING:
257                 printf("\t0x%.8x mapped to %s\n",
258                        propID, nameid->kind.lpwstr.Name);
259                 break;
260         }
261         talloc_free(nameid);
262
263         printf("\n\n7. GetProps (torture_namedprops property)\n");
264         propID = (propID & 0xFFFF0000) | PT_STRING8;
265         SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, propID);
266         retval = GetProps(&obj_message, SPropTagArray, &propvals, &cn_propvals);
267         MAPIFreeBuffer(SPropTagArray);
268         mapi_errstr("GetProps", GetLastError());
269         if (retval != MAPI_E_SUCCESS) return false;
270
271         mapidump_SPropValue(propvals[0], "\t");
272         MAPIFreeBuffer(propvals);
273
274         mapi_object_release(&obj_message);
275         mapi_object_release(&obj_folder);
276         mapi_object_release(&obj_store);
277
278         /* Uninitialize MAPI */
279         MAPIUninitialize();
280         talloc_free(mem_ctx);
281
282         return ret;
283 }