conversion.cpp 86 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328
  1. /*
  2. * Copyright 2005 - 2016 Zarafa and its licensors
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU Affero General Public License, version 3,
  6. * as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU Affero General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Affero General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. */
  17. #include <kopano/platform.h>
  18. #include <mapix.h>
  19. #include <mapidefs.h>
  20. #include <mapicode.h>
  21. #include <mapiutil.h>
  22. #include <edkmdb.h>
  23. #include <Python.h>
  24. #include <kopano/charset/convert.h>
  25. #include <kopano/conversion.h>
  26. #include "scl.h"
  27. // From Structs.py
  28. static PyObject *PyTypeSPropValue;
  29. static PyObject *PyTypeSSort;
  30. static PyObject *PyTypeSSortOrderSet;
  31. static PyObject *PyTypeSPropProblem;
  32. static PyObject *PyTypeMAPINAMEID;
  33. static PyObject *PyTypeMAPIError;
  34. static PyObject *PyTypeREADSTATE;
  35. static PyObject *PyTypeSTATSTG;
  36. static PyObject *PyTypeSYSTEMTIME;
  37. static PyObject *PyTypeNEWMAIL_NOTIFICATION;
  38. static PyObject *PyTypeOBJECT_NOTIFICATION;
  39. static PyObject *PyTypeTABLE_NOTIFICATION;
  40. static PyObject *PyTypeMVPROPMAP;
  41. static PyObject *PyTypeECUser;
  42. static PyObject *PyTypeECGroup;
  43. static PyObject *PyTypeECCompany;
  44. static PyObject *PyTypeECQuota;
  45. static PyObject *PyTypeECUserClientUpdateStatus;
  46. static PyObject *PyTypeECServer;
  47. static PyObject *PyTypeECQuotaStatus;
  48. static PyObject *PyTypeSAndRestriction;
  49. static PyObject *PyTypeSOrRestriction;
  50. static PyObject *PyTypeSNotRestriction;
  51. static PyObject *PyTypeSContentRestriction;
  52. static PyObject *PyTypeSBitMaskRestriction;
  53. static PyObject *PyTypeSPropertyRestriction;
  54. static PyObject *PyTypeSComparePropsRestriction;
  55. static PyObject *PyTypeSSizeRestriction;
  56. static PyObject *PyTypeSExistRestriction;
  57. static PyObject *PyTypeSSubRestriction;
  58. static PyObject *PyTypeSCommentRestriction;
  59. static PyObject *PyTypeActMoveCopy;
  60. static PyObject *PyTypeActReply;
  61. static PyObject *PyTypeActDeferAction;
  62. static PyObject *PyTypeActBounce;
  63. static PyObject *PyTypeActFwdDelegate;
  64. static PyObject *PyTypeActTag;
  65. static PyObject *PyTypeAction;
  66. static PyObject *PyTypeACTIONS;
  67. // From Time.py
  68. static PyObject *PyTypeFiletime;
  69. // Work around "bad argument to internal function"
  70. #if defined(_M_X64) || defined(__amd64__)
  71. #define PyLong_AsUINT64 PyLong_AsUnsignedLong
  72. #define PyLong_AsINT64 PyLong_AsLong
  73. #else
  74. #define PyLong_AsUINT64 PyLong_AsUnsignedLongLong
  75. #define PyLong_AsINT64 PyLong_AsLongLong
  76. #endif
  77. // Get Py_ssize_t for older versions of python
  78. #if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
  79. typedef int Py_ssize_t;
  80. # define PY_SSIZE_T_MAX INT_MAX
  81. # define PY_SSIZE_T_MIN INT_MIN
  82. #endif
  83. // Depending on native vs python unicode representation, set NATIVE_UNICODE
  84. #define WCHAR_T_SIZE __SIZEOF_WCHAR_T__
  85. #if (Py_UNICODE_SIZE == WCHAR_T_SIZE)
  86. #define NATIVE_UNICODE 1
  87. #else
  88. #define NATIVE_UNICODE 0
  89. #endif
  90. void Init()
  91. {
  92. PyObject *lpMAPIStruct = PyImport_ImportModule("MAPI.Struct");
  93. PyObject *lpMAPITime = PyImport_ImportModule("MAPI.Time");
  94. if(!lpMAPIStruct) {
  95. PyErr_SetString(PyExc_RuntimeError, "Unable to import MAPI.Struct");
  96. return;
  97. }
  98. if(!lpMAPITime) {
  99. PyErr_SetString(PyExc_RuntimeError, "Unable to import MAPI.Time");
  100. return;
  101. }
  102. PyTypeSPropValue = PyObject_GetAttrString(lpMAPIStruct, "SPropValue");
  103. PyTypeSPropProblem = PyObject_GetAttrString(lpMAPIStruct, "SPropProblem");
  104. PyTypeSSort = PyObject_GetAttrString(lpMAPIStruct, "SSort");
  105. PyTypeSSortOrderSet = PyObject_GetAttrString(lpMAPIStruct, "SSortOrderSet");
  106. PyTypeMAPINAMEID = PyObject_GetAttrString(lpMAPIStruct, "MAPINAMEID");
  107. PyTypeMAPIError = PyObject_GetAttrString(lpMAPIStruct, "MAPIError");
  108. PyTypeREADSTATE = PyObject_GetAttrString(lpMAPIStruct, "READSTATE");
  109. PyTypeSTATSTG = PyObject_GetAttrString(lpMAPIStruct, "STATSTG");
  110. PyTypeSYSTEMTIME = PyObject_GetAttrString(lpMAPIStruct, "SYSTEMTIME");
  111. PyTypeMVPROPMAP = PyObject_GetAttrString(lpMAPIStruct, "MVPROPMAP");
  112. PyTypeECUser = PyObject_GetAttrString(lpMAPIStruct, "ECUSER");
  113. PyTypeECGroup = PyObject_GetAttrString(lpMAPIStruct, "ECGROUP");
  114. PyTypeECCompany = PyObject_GetAttrString(lpMAPIStruct, "ECCOMPANY");
  115. PyTypeECQuota = PyObject_GetAttrString(lpMAPIStruct, "ECQUOTA");
  116. PyTypeECUserClientUpdateStatus = PyObject_GetAttrString(lpMAPIStruct, "ECUSERCLIENTUPDATESTATUS");
  117. PyTypeECServer = PyObject_GetAttrString(lpMAPIStruct, "ECSERVER");
  118. PyTypeECQuotaStatus = PyObject_GetAttrString(lpMAPIStruct, "ECQUOTASTATUS");
  119. PyTypeNEWMAIL_NOTIFICATION = PyObject_GetAttrString(lpMAPIStruct, "NEWMAIL_NOTIFICATION");
  120. PyTypeOBJECT_NOTIFICATION = PyObject_GetAttrString(lpMAPIStruct, "OBJECT_NOTIFICATION");
  121. PyTypeTABLE_NOTIFICATION = PyObject_GetAttrString(lpMAPIStruct, "TABLE_NOTIFICATION");
  122. PyTypeSAndRestriction = PyObject_GetAttrString(lpMAPIStruct, "SAndRestriction");
  123. PyTypeSOrRestriction = PyObject_GetAttrString(lpMAPIStruct, "SOrRestriction");
  124. PyTypeSNotRestriction = PyObject_GetAttrString(lpMAPIStruct, "SNotRestriction");
  125. PyTypeSContentRestriction = PyObject_GetAttrString(lpMAPIStruct, "SContentRestriction");
  126. PyTypeSBitMaskRestriction = PyObject_GetAttrString(lpMAPIStruct, "SBitMaskRestriction");
  127. PyTypeSPropertyRestriction = PyObject_GetAttrString(lpMAPIStruct, "SPropertyRestriction");
  128. PyTypeSComparePropsRestriction = PyObject_GetAttrString(lpMAPIStruct, "SComparePropsRestriction");
  129. PyTypeSSizeRestriction = PyObject_GetAttrString(lpMAPIStruct, "SSizeRestriction");
  130. PyTypeSExistRestriction = PyObject_GetAttrString(lpMAPIStruct, "SExistRestriction");
  131. PyTypeSSubRestriction = PyObject_GetAttrString(lpMAPIStruct, "SSubRestriction");
  132. PyTypeSCommentRestriction = PyObject_GetAttrString(lpMAPIStruct, "SCommentRestriction");
  133. PyTypeActMoveCopy = PyObject_GetAttrString(lpMAPIStruct, "actMoveCopy");
  134. PyTypeActReply = PyObject_GetAttrString(lpMAPIStruct, "actReply");
  135. PyTypeActDeferAction = PyObject_GetAttrString(lpMAPIStruct, "actDeferAction");
  136. PyTypeActBounce = PyObject_GetAttrString(lpMAPIStruct, "actBounce");
  137. PyTypeActFwdDelegate = PyObject_GetAttrString(lpMAPIStruct, "actFwdDelegate");
  138. PyTypeActTag = PyObject_GetAttrString(lpMAPIStruct, "actTag");
  139. PyTypeAction = PyObject_GetAttrString(lpMAPIStruct, "ACTION");
  140. PyTypeACTIONS = PyObject_GetAttrString(lpMAPIStruct, "ACTIONS");
  141. PyTypeFiletime = PyObject_GetAttrString(lpMAPITime, "FileTime");
  142. }
  143. // Coerce PyObject into PyUnicodeObject, copy and zero-terminate
  144. wchar_t * CopyPyUnicode(wchar_t **lpWide, PyObject *o, void *lpBase)
  145. {
  146. PyObject *unicode = NULL;
  147. int size;
  148. unicode = PyUnicode_FromObject(o);
  149. if(!unicode) {
  150. *lpWide = NULL;
  151. return NULL;
  152. }
  153. size = PyUnicode_GetSize(unicode);
  154. if (MAPIAllocateMore((size + 1) * sizeof(wchar_t), lpBase, (void **)lpWide) == hrSuccess) {
  155. #if PY_MAJOR_VERSION >= 3
  156. PyUnicode_AsWideChar(unicode, *lpWide, size);
  157. #else
  158. PyUnicode_AsWideChar((PyUnicodeObject *)unicode, *lpWide, size);
  159. #endif
  160. (*lpWide)[size] = '\0';
  161. Py_DECREF(unicode);
  162. return *lpWide;
  163. }
  164. Py_DECREF(unicode);
  165. return NULL;
  166. }
  167. int Object_is_list_of(PyObject *object, TypeCheckFunc fnTypeCheck)
  168. {
  169. int rc = 1;
  170. PyObject *iter = NULL;
  171. PyObject *elem = NULL;
  172. if (object == Py_None)
  173. return 0;
  174. iter = PyObject_GetIter(object);
  175. if (!iter)
  176. return 0;
  177. while (rc == 1 && (elem = PyIter_Next(iter))) {
  178. rc = fnTypeCheck(elem);
  179. Py_DECREF(elem);
  180. elem = NULL;
  181. }
  182. Py_DECREF(iter);
  183. return rc;
  184. }
  185. FILETIME Object_to_FILETIME(PyObject *object)
  186. {
  187. FILETIME ft = {0, 0};
  188. unsigned long long periods = 0;
  189. PyObject *filetime = PyObject_GetAttrString(object, "filetime");
  190. if (!filetime) {
  191. PyErr_Format(PyExc_TypeError, "PT_SYSTIME object does not have 'filetime' attribute");
  192. return ft;
  193. }
  194. #if PY_MAJOR_VERSION >= 3
  195. periods = PyLong_AsUnsignedLongLongMask(filetime);
  196. #else
  197. periods = PyInt_AsUnsignedLongLongMask(filetime);
  198. #endif
  199. ft.dwHighDateTime = periods >> 32;
  200. ft.dwLowDateTime = periods & 0xffffffff;
  201. return ft;
  202. }
  203. PyObject *Object_from_FILETIME(FILETIME ft)
  204. {
  205. PyObject *object = NULL;
  206. PyObject *filetime = NULL;
  207. filetime = PyLong_FromUnsignedLongLong(((unsigned long long)ft.dwHighDateTime << 32) + ft.dwLowDateTime);
  208. if (PyErr_Occurred())
  209. goto exit;
  210. object = PyObject_CallFunction(PyTypeFiletime, "(O)", filetime);
  211. exit:
  212. if (filetime != NULL)
  213. Py_DECREF(filetime);
  214. return object;
  215. }
  216. int Object_is_FILETIME(PyObject *object)
  217. {
  218. return PyObject_IsInstance(object, PyTypeFiletime);
  219. }
  220. PyObject *Object_from_SPropValue(const SPropValue *lpProp)
  221. {
  222. PyObject *Value = NULL;
  223. PyObject *ulPropTag = NULL;
  224. PyObject *object = NULL;
  225. ulPropTag = PyLong_FromUnsignedLong(lpProp->ulPropTag);
  226. switch(PROP_TYPE(lpProp->ulPropTag)) {
  227. case PT_STRING8:
  228. Value = PyString_FromString(lpProp->Value.lpszA);
  229. break;
  230. case PT_UNICODE:
  231. Value = PyUnicode_FromWideChar(lpProp->Value.lpszW, wcslen(lpProp->Value.lpszW));
  232. break;
  233. case PT_BINARY:
  234. Value = PyString_FromStringAndSize((const char *)lpProp->Value.bin.lpb, lpProp->Value.bin.cb);
  235. break;
  236. case PT_SHORT:
  237. Value = PyLong_FromLong(lpProp->Value.i);
  238. break;
  239. case PT_ERROR:
  240. Value = PyLong_FromUnsignedLong((unsigned int)lpProp->Value.err);
  241. break;
  242. case PT_LONG:
  243. Value = PyLong_FromLongLong(lpProp->Value.l); // We have to use LongLong since it could be either PT_LONG or PT_ULONG. 'Long' doesn't cover the range
  244. break;
  245. case PT_FLOAT:
  246. Value = PyFloat_FromDouble(lpProp->Value.flt);
  247. break;
  248. case PT_APPTIME:
  249. case PT_DOUBLE:
  250. Value = PyFloat_FromDouble(lpProp->Value.dbl);
  251. break;
  252. case PT_LONGLONG:
  253. case PT_CURRENCY:
  254. Value = PyLong_FromLongLong(lpProp->Value.cur.int64);
  255. break;
  256. case PT_BOOLEAN:
  257. Value = PyBool_FromLong(lpProp->Value.b);
  258. break;
  259. case PT_SYSTIME:
  260. Value = Object_from_FILETIME(lpProp->Value.ft);
  261. break;
  262. case PT_CLSID:
  263. Value = PyString_FromStringAndSize((const char *)lpProp->Value.lpguid, sizeof(GUID));
  264. break;
  265. case PT_OBJECT:
  266. Py_INCREF(Py_None);
  267. Value = Py_None;
  268. break;
  269. case PT_SRESTRICTION:
  270. Value = Object_from_LPSRestriction((LPSRestriction)lpProp->Value.lpszA);
  271. break;
  272. case PT_ACTIONS:
  273. Value = Object_from_LPACTIONS((ACTIONS *)lpProp->Value.lpszA);
  274. break;
  275. #define BASE(x) x
  276. #define INT64(x) x.int64
  277. #define QUADPART(x) x.QuadPart
  278. #define PT_MV_CASE(MVname,MVelem,From,Sub) \
  279. Value = PyList_New(0); \
  280. for (unsigned int i = 0; i < lpProp->Value.MV##MVname.cValues; ++i) { \
  281. PyObject *elem = From(Sub(lpProp->Value.MV##MVname.lp##MVelem[i])); \
  282. PyList_Append(Value, elem); \
  283. Py_DECREF(elem); \
  284. } \
  285. break;
  286. case PT_MV_SHORT:
  287. PT_MV_CASE(i, i, PyLong_FromLong,BASE)
  288. case PT_MV_LONG:
  289. PT_MV_CASE(l, l, PyLong_FromLong,BASE)
  290. case PT_MV_FLOAT:
  291. PT_MV_CASE(flt, flt, PyFloat_FromDouble,BASE)
  292. case PT_MV_DOUBLE:
  293. PT_MV_CASE(dbl, dbl, PyFloat_FromDouble,BASE)
  294. case PT_MV_CURRENCY:
  295. PT_MV_CASE(cur, cur, PyLong_FromLongLong,INT64)
  296. case PT_MV_APPTIME:
  297. PT_MV_CASE(at, at, PyFloat_FromDouble,BASE)
  298. case PT_MV_LONGLONG:
  299. PT_MV_CASE(li, li, PyLong_FromLongLong,QUADPART)
  300. case PT_MV_SYSTIME:
  301. Value = PyList_New(0);
  302. for (unsigned int i = 0; i < lpProp->Value.MVft.cValues; ++i) {
  303. PyObject *elem = Object_from_FILETIME(lpProp->Value.MVft.lpft[i]);
  304. PyList_Append(Value, elem);
  305. Py_DECREF(elem);
  306. }
  307. break;
  308. case PT_MV_STRING8:
  309. PT_MV_CASE(szA, pszA, PyString_FromString, BASE)
  310. case PT_MV_BINARY:
  311. Value = PyList_New(0);
  312. for (unsigned int i = 0; i < lpProp->Value.MVbin.cValues; ++i) {
  313. PyObject *elem = PyString_FromStringAndSize((const char *)lpProp->Value.MVbin.lpbin[i].lpb, lpProp->Value.MVbin.lpbin[i].cb);
  314. PyList_Append(Value, elem);
  315. Py_DECREF(elem);
  316. }
  317. break;
  318. case PT_MV_UNICODE:
  319. Value = PyList_New(0);
  320. for (unsigned int i = 0; i < lpProp->Value.MVszW.cValues; ++i) {
  321. int len = wcslen(lpProp->Value.MVszW.lppszW[i]);
  322. PyObject *elem = PyUnicode_FromWideChar(lpProp->Value.MVszW.lppszW[i], len);
  323. PyList_Append(Value, elem);
  324. Py_DECREF(elem);
  325. }
  326. break;
  327. case PT_MV_CLSID:
  328. Value = PyList_New(0);
  329. for (unsigned int i = 0; i < lpProp->Value.MVguid.cValues; ++i) {
  330. PyObject *elem = PyString_FromStringAndSize((const char *)&lpProp->Value.MVguid.lpguid[i], sizeof(GUID));
  331. PyList_Append(Value, elem);
  332. Py_DECREF(elem);
  333. }
  334. break;
  335. case PT_NULL:
  336. Py_INCREF(Py_None);
  337. Value = Py_None;
  338. break;
  339. default:
  340. PyErr_Format(PyExc_RuntimeError, "Bad property type %x", PROP_TYPE(lpProp->ulPropTag));
  341. break;
  342. }
  343. if (PyErr_Occurred())
  344. goto exit;
  345. object = PyObject_CallFunction(PyTypeSPropValue, "(OO)", ulPropTag, Value);
  346. exit:
  347. if (Value != nullptr)
  348. Py_DECREF(Value);
  349. if (ulPropTag != nullptr)
  350. Py_DECREF(ulPropTag);
  351. return object;
  352. }
  353. PyObject *Object_from_LPSPropValue(const SPropValue *prop)
  354. {
  355. return Object_from_SPropValue(prop);
  356. }
  357. int Object_is_LPSPropValue(PyObject *object)
  358. {
  359. return PyObject_IsInstance(object, PyTypeSPropValue);
  360. }
  361. PyObject *List_from_SPropValue(const SPropValue *lpProps, ULONG cValues)
  362. {
  363. PyObject *list = PyList_New(0);
  364. PyObject *item = NULL;
  365. for (unsigned int i = 0; i < cValues; ++i) {
  366. item = Object_from_LPSPropValue(&lpProps[i]);
  367. if(PyErr_Occurred())
  368. goto exit;
  369. PyList_Append(list, item);
  370. Py_DECREF(item);
  371. item = NULL;
  372. }
  373. exit:
  374. if(PyErr_Occurred()) {
  375. if (list != nullptr)
  376. Py_DECREF(list);
  377. list = NULL;
  378. }
  379. if (item != nullptr)
  380. Py_DECREF(item);
  381. return list;
  382. }
  383. PyObject *List_from_LPSPropValue(const SPropValue *props, ULONG vals)
  384. {
  385. return List_from_SPropValue(props, vals);
  386. }
  387. PyObject * List_from_wchar_t(wchar_t **lpStrings, ULONG cElements)
  388. {
  389. PyObject *list = PyList_New(0);
  390. PyObject *item = NULL;
  391. for (unsigned int i = 0; i < cElements; ++i) {
  392. item = PyUnicode_FromWideChar(lpStrings[i], wcslen(lpStrings[i]));
  393. if(PyErr_Occurred())
  394. goto exit;
  395. PyList_Append(list, item);
  396. Py_DECREF(item);
  397. item = NULL;
  398. }
  399. exit:
  400. if(PyErr_Occurred()) {
  401. if (list != nullptr)
  402. Py_DECREF(list);
  403. list = NULL;
  404. }
  405. if (item != nullptr)
  406. Py_DECREF(item);
  407. return list;
  408. }
  409. void Object_to_p_SPropValue(PyObject *object, SPropValue *lpProp,
  410. ULONG ulFlags, void *lpBase)
  411. {
  412. PyObject *ulPropTag = NULL;
  413. PyObject *Value = NULL;
  414. char *lpstr = NULL;
  415. Py_ssize_t size = 0;
  416. ulPropTag = PyObject_GetAttrString(object, "ulPropTag");
  417. Value = PyObject_GetAttrString(object, "Value");
  418. if(!ulPropTag || !Value) {
  419. PyErr_SetString(PyExc_RuntimeError, "ulPropTag or Value missing from SPropValue");
  420. goto exit;
  421. }
  422. lpProp->dwAlignPad = 0;
  423. lpProp->ulPropTag = (ULONG)PyLong_AsUnsignedLong(ulPropTag);
  424. switch(PROP_TYPE(lpProp->ulPropTag)) {
  425. case PT_NULL:
  426. lpProp->Value.x = 0;
  427. break;
  428. case PT_STRING8:
  429. if (ulFlags == CONV_COPY_SHALLOW)
  430. lpProp->Value.lpszA = PyString_AsString(Value);
  431. else {
  432. PyString_AsStringAndSize(Value, &lpstr, &size);
  433. if (MAPIAllocateMore(size + 1, lpBase, (LPVOID *)&lpProp->Value.lpszA) != hrSuccess)
  434. goto exit;
  435. memcpy(lpProp->Value.lpszA, lpstr, size + 1);
  436. }
  437. break;
  438. case PT_UNICODE:
  439. // @todo add PyUnicode_Check call?
  440. if (ulFlags == CONV_COPY_SHALLOW && NATIVE_UNICODE)
  441. lpProp->Value.lpszW = (WCHAR *)PyUnicode_AsUnicode(Value);
  442. else
  443. CopyPyUnicode(&lpProp->Value.lpszW, Value, lpBase);
  444. break;
  445. case PT_ERROR:
  446. lpProp->Value.ul = (ULONG)PyLong_AsUnsignedLong(Value);
  447. break;
  448. case PT_SHORT:
  449. lpProp->Value.i = (short int)PyLong_AsLong(Value);
  450. break;
  451. case PT_LONG:
  452. lpProp->Value.ul = (ULONG)PyLong_AsLongLong(Value); // We have to use LongLong since it could be either PT_LONG or PT_ULONG. 'Long' doesn't cover the range
  453. break;
  454. case PT_FLOAT:
  455. lpProp->Value.flt = (float)PyFloat_AsDouble(Value);
  456. break;
  457. case PT_APPTIME:
  458. case PT_DOUBLE:
  459. lpProp->Value.dbl = PyFloat_AsDouble(Value);
  460. break;
  461. case PT_LONGLONG:
  462. case PT_CURRENCY:
  463. lpProp->Value.cur.int64 = PyLong_AsINT64(Value);
  464. break;
  465. case PT_BOOLEAN:
  466. lpProp->Value.b = (Value == Py_True);
  467. break;
  468. case PT_OBJECT:
  469. lpProp->Value.lpszA = NULL;
  470. break;
  471. case PT_SYSTIME:
  472. lpProp->Value.ft = Object_to_FILETIME(Value);
  473. break;
  474. case PT_CLSID:
  475. PyString_AsStringAndSize(Value, &lpstr, &size);
  476. if (size == sizeof(GUID)) {
  477. if (ulFlags == CONV_COPY_SHALLOW)
  478. lpProp->Value.lpguid = (LPGUID)lpstr;
  479. else {
  480. if (MAPIAllocateMore(sizeof(GUID), lpBase, (LPVOID *)&lpProp->Value.lpguid) != hrSuccess)
  481. goto exit;
  482. memcpy(lpProp->Value.lpguid, lpstr, sizeof(GUID));
  483. }
  484. }
  485. else
  486. PyErr_Format(PyExc_TypeError, "PT_CLSID Value must be exactly %d bytes", (int)sizeof(GUID));
  487. break;
  488. case PT_BINARY:
  489. PyString_AsStringAndSize(Value, &lpstr, &size);
  490. if (ulFlags == CONV_COPY_SHALLOW)
  491. lpProp->Value.bin.lpb = (LPBYTE)lpstr;
  492. else {
  493. if (MAPIAllocateMore(size, lpBase, (LPVOID *)&lpProp->Value.bin.lpb) != hrSuccess)
  494. goto exit;
  495. memcpy(lpProp->Value.bin.lpb, lpstr, size);
  496. }
  497. lpProp->Value.bin.cb = size;
  498. break;
  499. case PT_SRESTRICTION:
  500. if (MAPIAllocateMore(sizeof(SRestriction), lpBase, (void **)&lpProp->Value.lpszA) != hrSuccess)
  501. goto exit;
  502. Object_to_LPSRestriction(Value, (LPSRestriction)lpProp->Value.lpszA, lpBase);
  503. break;
  504. case PT_ACTIONS:
  505. if (MAPIAllocateMore(sizeof(ACTIONS), lpBase, (void **)&lpProp->Value.lpszA) != hrSuccess)
  506. goto exit;
  507. Object_to_LPACTIONS(Value, (ACTIONS*)lpProp->Value.lpszA, lpBase);
  508. break;
  509. #undef PT_MV_CASE
  510. #define PT_MV_CASE(MVname,MVelem,As,Sub) \
  511. { \
  512. Py_ssize_t len = PyObject_Size(Value); \
  513. PyObject *iter = PyObject_GetIter(Value); \
  514. PyObject *elem = NULL; \
  515. int n = 0; \
  516. \
  517. if (len) { \
  518. if (MAPIAllocateMore(sizeof(*lpProp->Value.MV##MVname.lp##MVelem) * len, lpBase, (void **)&lpProp->Value.MV##MVname.lp##MVelem) != hrSuccess) \
  519. goto exit; \
  520. while ((elem = PyIter_Next(iter))) { \
  521. Sub(lpProp->Value.MV##MVname.lp##MVelem[n]) = As(elem); \
  522. Py_DECREF(elem); \
  523. ++n; \
  524. } \
  525. } \
  526. lpProp->Value.MV##MVname.cValues = n; \
  527. Py_DECREF(iter); \
  528. break; \
  529. }
  530. case PT_MV_SHORT:
  531. PT_MV_CASE(i,i,PyLong_AsLong,BASE)
  532. case PT_MV_LONG:
  533. PT_MV_CASE(l,l,PyLong_AsLong,BASE)
  534. case PT_MV_FLOAT:
  535. PT_MV_CASE(flt,flt,PyFloat_AsDouble,BASE)
  536. case PT_MV_DOUBLE:
  537. PT_MV_CASE(dbl,dbl,PyFloat_AsDouble,BASE)
  538. case PT_MV_CURRENCY:
  539. PT_MV_CASE(cur,cur,PyLong_AsINT64,INT64)
  540. case PT_MV_APPTIME:
  541. PT_MV_CASE(at,at,PyFloat_AsDouble,BASE)
  542. case PT_MV_LONGLONG:
  543. PT_MV_CASE(li,li,PyLong_AsINT64,QUADPART)
  544. case PT_MV_SYSTIME:
  545. {
  546. Py_ssize_t len = PyObject_Size(Value);
  547. PyObject *iter = PyObject_GetIter(Value);
  548. PyObject *elem = NULL;
  549. int n = 0;
  550. if (MAPIAllocateMore(sizeof(SDateTimeArray) * len, lpBase, (void **)&lpProp->Value.MVft.lpft) != hrSuccess)
  551. goto exit;
  552. while ((elem = PyIter_Next(iter))) {
  553. lpProp->Value.MVft.lpft[n] = Object_to_FILETIME(elem);
  554. Py_DECREF(elem);
  555. ++n;
  556. }
  557. lpProp->Value.MVft.cValues = n;
  558. Py_DECREF(iter);
  559. break;
  560. }
  561. case PT_MV_STRING8:
  562. {
  563. Py_ssize_t len = PyObject_Size(Value);
  564. PyObject *iter = PyObject_GetIter(Value);
  565. PyObject *elem = NULL;
  566. int n = 0;
  567. if (MAPIAllocateMore(sizeof(*lpProp->Value.MVszA.lppszA) * len, lpBase, (LPVOID *)&lpProp->Value.MVszA.lppszA) != hrSuccess)
  568. goto exit;
  569. while ((elem = PyIter_Next(iter))) {
  570. if (ulFlags == CONV_COPY_SHALLOW)
  571. lpProp->Value.MVszA.lppszA[n] = PyString_AsString(elem);
  572. else {
  573. PyString_AsStringAndSize(elem, &lpstr, &size);
  574. if (MAPIAllocateMore(size+1, lpBase, (LPVOID *)&lpProp->Value.MVszA.lppszA[n]) != hrSuccess)
  575. goto exit;
  576. memcpy(lpProp->Value.MVszA.lppszA[n], lpstr, size+1);
  577. }
  578. Py_DECREF(elem);
  579. ++n;
  580. }
  581. lpProp->Value.MVszA.cValues = n;
  582. Py_DECREF(iter);
  583. break;
  584. }
  585. case PT_MV_BINARY:
  586. {
  587. Py_ssize_t len = PyObject_Size(Value);
  588. PyObject *iter = PyObject_GetIter(Value);
  589. PyObject *elem = NULL;
  590. int n = 0;
  591. if (MAPIAllocateMore(sizeof(SBinaryArray) * len, lpBase, (void **)&lpProp->Value.MVbin.lpbin) != hrSuccess)
  592. goto exit;
  593. while ((elem = PyIter_Next(iter))) {
  594. PyString_AsStringAndSize(elem, &lpstr, &size);
  595. if (ulFlags == CONV_COPY_SHALLOW)
  596. lpProp->Value.MVbin.lpbin[n].lpb = (LPBYTE)lpstr;
  597. else {
  598. if (MAPIAllocateMore(size, lpBase, (LPVOID *)&lpProp->Value.MVbin.lpbin[n].lpb) != hrSuccess)
  599. goto exit;
  600. memcpy(lpProp->Value.MVbin.lpbin[n].lpb, lpstr, size);
  601. }
  602. lpProp->Value.MVbin.lpbin[n].cb = size;
  603. Py_DECREF(elem);
  604. ++n;
  605. }
  606. lpProp->Value.MVbin.cValues = n;
  607. Py_DECREF(iter);
  608. break;
  609. }
  610. case PT_MV_UNICODE:
  611. {
  612. Py_ssize_t len = PyObject_Size(Value);
  613. PyObject *iter = PyObject_GetIter(Value);
  614. PyObject *elem = NULL;
  615. int n = 0;
  616. if (MAPIAllocateMore(sizeof(*lpProp->Value.MVszW.lppszW) * len, lpBase, (LPVOID *)&lpProp->Value.MVszW.lppszW) != hrSuccess)
  617. goto exit;
  618. while((elem = PyIter_Next(iter))) {
  619. if (ulFlags == CONV_COPY_SHALLOW && NATIVE_UNICODE)
  620. lpProp->Value.MVszW.lppszW[n] = (WCHAR*)PyUnicode_AsUnicode(elem);
  621. else
  622. CopyPyUnicode(&lpProp->Value.MVszW.lppszW[n], Value, lpBase);
  623. Py_DECREF(elem);
  624. ++n;
  625. }
  626. lpProp->Value.MVszW.cValues = n;
  627. Py_DECREF(iter);
  628. break;
  629. }
  630. case PT_MV_CLSID:
  631. {
  632. Py_ssize_t len = PyObject_Size(Value);
  633. PyObject *iter = PyObject_GetIter(Value);
  634. PyObject *elem = NULL;
  635. int n = 0;
  636. char *guid;
  637. if (MAPIAllocateMore(sizeof(GUID) * len, lpBase, (void **)&lpProp->Value.MVguid.lpguid) != hrSuccess)
  638. goto exit;
  639. while ((elem = PyIter_Next(iter))) {
  640. PyString_AsStringAndSize(elem, &guid, &size);
  641. if (size != sizeof(GUID)) {
  642. PyErr_Format(PyExc_TypeError, "PT_CLSID Value must be exactly %d bytes", (int)sizeof(GUID));
  643. break;
  644. }
  645. memcpy(&lpProp->Value.MVguid.lpguid[n], guid, size);
  646. Py_DECREF(elem);
  647. ++n;
  648. }
  649. lpProp->Value.MVguid.cValues = n;
  650. Py_DECREF(iter);
  651. break;
  652. }
  653. default:
  654. PyErr_Format(PyExc_TypeError, "ulPropTag has unknown type %x", PROP_TYPE(lpProp->ulPropTag));
  655. break;
  656. }
  657. exit:
  658. if (ulPropTag)
  659. Py_DECREF(ulPropTag);
  660. if (Value)
  661. Py_DECREF(Value);
  662. }
  663. void Object_to_LPSPropValue(PyObject *object, SPropValue *prop,
  664. ULONG flags, void *base)
  665. {
  666. Object_to_p_SPropValue(object, prop, flags, base);
  667. }
  668. SPropValue *Object_to_p_SPropValue(PyObject *object, ULONG ulFlags,
  669. void *lpBase)
  670. {
  671. LPSPropValue lpProp = NULL;
  672. if(lpBase) {
  673. if (MAPIAllocateMore(sizeof(SPropValue), lpBase, (void **)&lpProp) != hrSuccess)
  674. return NULL;
  675. }
  676. else {
  677. if (MAPIAllocateBuffer(sizeof(SPropValue), (void **)&lpProp) != hrSuccess)
  678. return NULL;
  679. lpBase = lpProp;
  680. }
  681. Object_to_LPSPropValue(object, lpProp, ulFlags, lpBase);
  682. if (!PyErr_Occurred())
  683. return lpProp;
  684. if (!lpBase)
  685. MAPIFreeBuffer(lpProp);
  686. return NULL;
  687. }
  688. SPropValue *Object_to_LPSPropValue(PyObject *object, ULONG flags, void *base)
  689. {
  690. return Object_to_p_SPropValue(object, flags, base);
  691. }
  692. SPropValue *List_to_p_SPropValue(PyObject *object, ULONG *cValues,
  693. ULONG ulFlags, void *lpBase)
  694. {
  695. Py_ssize_t size = 0;
  696. LPSPropValue lpProps = NULL;
  697. LPSPropValue lpResult = NULL;
  698. PyObject *iter = NULL;
  699. PyObject *elem = NULL;
  700. int i = 0;
  701. if(object == Py_None) {
  702. *cValues = 0;
  703. return NULL;
  704. }
  705. iter = PyObject_GetIter(object);
  706. if(!iter)
  707. goto exit;
  708. size = PyObject_Size(object);
  709. if(lpBase != nullptr) {
  710. if (MAPIAllocateMore(sizeof(SPropValue)*size, lpBase, reinterpret_cast<void**>(&lpProps)) != hrSuccess)
  711. goto exit;
  712. } else {
  713. if (MAPIAllocateBuffer(sizeof(SPropValue)*size, reinterpret_cast<void**>(&lpProps)) != hrSuccess)
  714. goto exit;
  715. }
  716. memset(lpProps, 0, sizeof(SPropValue)*size);
  717. while((elem = PyIter_Next(iter))) {
  718. Object_to_LPSPropValue(elem, &lpProps[i], ulFlags, lpProps);
  719. if(PyErr_Occurred())
  720. goto exit;
  721. Py_DECREF(elem);
  722. elem = NULL;
  723. ++i;
  724. }
  725. lpResult = lpProps;
  726. *cValues = size;
  727. exit:
  728. if (PyErr_Occurred() && lpBase == nullptr)
  729. MAPIFreeBuffer(lpProps);
  730. if (elem != nullptr)
  731. Py_DECREF(elem);
  732. if (iter != nullptr)
  733. Py_DECREF(iter);
  734. return lpResult;
  735. }
  736. SPropValue *List_to_LPSPropValue(PyObject *object, ULONG *pvals,
  737. ULONG flags, void *base)
  738. {
  739. return List_to_p_SPropValue(object, pvals, flags, base);
  740. }
  741. PyObject * List_from_LPTSTRPtr(LPTSTR *lpStrings, ULONG cValues)
  742. {
  743. PyErr_SetString(PyExc_RuntimeError, "LPSSTRPtr unsupported");
  744. return NULL;
  745. }
  746. SPropTagArray *List_to_p_SPropTagArray(PyObject *object, ULONG /*ulFlags*/)
  747. {
  748. PyObject *elem = NULL;
  749. PyObject *iter = NULL;
  750. Py_ssize_t len = 0;
  751. LPSPropTagArray lpPropTagArray = NULL;
  752. int n = 0;
  753. if(object == Py_None)
  754. return NULL;
  755. len = PyObject_Length(object);
  756. if(len < 0) {
  757. PyErr_Format(PyExc_TypeError, "Invalid list passed as property list");
  758. goto exit;
  759. }
  760. if (MAPIAllocateBuffer(CbNewSPropTagArray(len), (void **)&lpPropTagArray) != hrSuccess)
  761. goto exit;
  762. iter = PyObject_GetIter(object);
  763. if(iter == NULL)
  764. goto exit;
  765. while((elem = PyIter_Next(iter))) {
  766. lpPropTagArray->aulPropTag[n] = (ULONG)PyLong_AsUnsignedLong(elem);
  767. Py_DECREF(elem);
  768. ++n;
  769. }
  770. lpPropTagArray->cValues = n;
  771. exit:
  772. if(PyErr_Occurred()) {
  773. MAPIFreeBuffer(lpPropTagArray);
  774. lpPropTagArray = NULL;
  775. }
  776. if (iter != nullptr)
  777. Py_DECREF(iter);
  778. return lpPropTagArray;
  779. }
  780. PyObject *List_from_SPropTagArray(const SPropTagArray *lpPropTagArray)
  781. {
  782. PyObject *list = NULL;
  783. PyObject *elem = NULL;
  784. if(lpPropTagArray == NULL) {
  785. Py_INCREF(Py_None);
  786. return Py_None;
  787. }
  788. list = PyList_New(0);
  789. for (unsigned int i = 0; i < lpPropTagArray->cValues; ++i) {
  790. elem = PyLong_FromUnsignedLong(lpPropTagArray->aulPropTag[i]);
  791. PyList_Append(list, elem);
  792. if(PyErr_Occurred())
  793. goto exit;
  794. Py_DECREF(elem);
  795. elem = NULL;
  796. }
  797. exit:
  798. if (elem != nullptr)
  799. Py_DECREF(elem);
  800. if(PyErr_Occurred()) {
  801. Py_DECREF(list);
  802. list = NULL;
  803. }
  804. return list;
  805. }
  806. SPropTagArray *List_to_LPSPropTagArray(PyObject *obj, ULONG flags)
  807. {
  808. return List_to_p_SPropTagArray(obj, flags);
  809. }
  810. PyObject *List_from_LPSPropTagArray(const SPropTagArray *a)
  811. {
  812. return List_from_SPropTagArray(a);
  813. }
  814. void Object_to_LPSRestriction(PyObject *object, LPSRestriction lpsRestriction, void *lpBase)
  815. {
  816. PyObject *rt = NULL;
  817. PyObject *iter = NULL;
  818. PyObject *sub = NULL;
  819. PyObject *elem = NULL;
  820. PyObject *ulPropTag = NULL, *ulPropTag2 = NULL, *ulMask = NULL, *cb = NULL, *ulFuzzyLevel = NULL, *relop = NULL, *lpProp = NULL;
  821. Py_ssize_t len;
  822. int n = 0;
  823. if(lpBase == NULL)
  824. lpBase = lpsRestriction;
  825. rt = PyObject_GetAttrString(object, "rt");
  826. if(!rt) {
  827. PyErr_SetString(PyExc_RuntimeError, "rt (type) missing for restriction");
  828. goto exit;
  829. }
  830. lpsRestriction->rt = (ULONG)PyLong_AsUnsignedLong(rt);
  831. switch(lpsRestriction->rt) {
  832. case RES_AND:
  833. case RES_OR:
  834. sub = PyObject_GetAttrString(object, "lpRes");
  835. if(!sub) {
  836. PyErr_SetString(PyExc_RuntimeError, "lpRes missing for restriction");
  837. goto exit;
  838. }
  839. len = PyObject_Length(sub);
  840. // Handle RES_AND and RES_OR the same since they are binary-compatible
  841. if (MAPIAllocateMore(sizeof(SRestriction) * len, lpBase, (void **)&lpsRestriction->res.resAnd.lpRes) != hrSuccess) {
  842. PyErr_SetString(PyExc_RuntimeError, "Out of memory");
  843. goto exit;
  844. }
  845. iter = PyObject_GetIter(sub);
  846. if(iter == NULL)
  847. goto exit;
  848. while((elem = PyIter_Next(iter))) {
  849. Object_to_LPSRestriction(elem, &lpsRestriction->res.resAnd.lpRes[n], lpBase);
  850. if(PyErr_Occurred())
  851. goto exit;
  852. ++n;
  853. Py_DECREF(elem);
  854. elem = NULL;
  855. }
  856. lpsRestriction->res.resAnd.cRes = n;
  857. break;
  858. case RES_NOT:
  859. sub = PyObject_GetAttrString(object, "lpRes");
  860. if(!sub) {
  861. PyErr_SetString(PyExc_RuntimeError, "lpRes missing for restriction");
  862. goto exit;
  863. }
  864. if (MAPIAllocateMore(sizeof(SRestriction), lpBase, (void **)&lpsRestriction->res.resNot.lpRes) != hrSuccess) {
  865. PyErr_SetString(PyExc_RuntimeError, "Out of memory");
  866. goto exit;
  867. }
  868. Object_to_LPSRestriction(sub, lpsRestriction->res.resNot.lpRes, lpBase);
  869. if(PyErr_Occurred())
  870. goto exit;
  871. break;
  872. case RES_CONTENT:
  873. ulFuzzyLevel = PyObject_GetAttrString(object, "ulFuzzyLevel");
  874. ulPropTag = PyObject_GetAttrString(object, "ulPropTag");
  875. sub = PyObject_GetAttrString(object, "lpProp");
  876. if(!ulFuzzyLevel || ! ulPropTag || !sub) {
  877. PyErr_SetString(PyExc_RuntimeError, "ulFuzzyLevel, ulPropTag or lpProp missing for RES_CONTENT restriction");
  878. goto exit;
  879. }
  880. lpsRestriction->res.resContent.ulFuzzyLevel = PyLong_AsUnsignedLong(ulFuzzyLevel);
  881. lpsRestriction->res.resContent.ulPropTag = PyLong_AsUnsignedLong(ulPropTag);
  882. lpsRestriction->res.resContent.lpProp = Object_to_LPSPropValue(sub, CONV_COPY_SHALLOW, lpBase);
  883. break;
  884. case RES_PROPERTY:
  885. relop = PyObject_GetAttrString(object, "relop");
  886. ulPropTag = PyObject_GetAttrString(object, "ulPropTag");
  887. sub = PyObject_GetAttrString(object, "lpProp");
  888. if(!relop || !ulPropTag || !sub) {
  889. PyErr_SetString(PyExc_RuntimeError, "relop, ulPropTag or lpProp missing for RES_PROPERTY restriction");
  890. goto exit;
  891. }
  892. lpsRestriction->res.resProperty.relop = PyLong_AsUnsignedLong(relop);
  893. lpsRestriction->res.resProperty.ulPropTag = PyLong_AsUnsignedLong(ulPropTag);
  894. lpsRestriction->res.resProperty.lpProp = Object_to_LPSPropValue(sub, CONV_COPY_SHALLOW, lpBase);
  895. break;
  896. case RES_COMPAREPROPS:
  897. relop = PyObject_GetAttrString(object, "relop");
  898. ulPropTag = PyObject_GetAttrString(object, "ulPropTag1");
  899. ulPropTag2 = PyObject_GetAttrString(object, "ulPropTag2");
  900. if(!relop || !ulPropTag || !ulPropTag2) {
  901. PyErr_SetString(PyExc_RuntimeError, "relop, ulPropTag1 or ulPropTag2 missing for RES_COMPAREPROPS restriction");
  902. goto exit;
  903. }
  904. lpsRestriction->res.resCompareProps.relop = PyLong_AsUnsignedLong(relop);
  905. lpsRestriction->res.resCompareProps.ulPropTag1 = PyLong_AsUnsignedLong(ulPropTag);
  906. lpsRestriction->res.resCompareProps.ulPropTag2 = PyLong_AsUnsignedLong(ulPropTag2);
  907. break;
  908. case RES_BITMASK:
  909. relop = PyObject_GetAttrString(object, "relBMR");
  910. ulPropTag = PyObject_GetAttrString(object, "ulPropTag");
  911. ulMask = PyObject_GetAttrString(object, "ulMask");
  912. if(!relop || !ulPropTag || !ulMask) {
  913. PyErr_SetString(PyExc_RuntimeError, "relBMR, ulPropTag or ulMask missing for RES_BITMASK restriction");
  914. goto exit;
  915. }
  916. lpsRestriction->res.resBitMask.relBMR = PyLong_AsUnsignedLong(relop);
  917. lpsRestriction->res.resBitMask.ulPropTag = PyLong_AsUnsignedLong(ulPropTag);
  918. lpsRestriction->res.resBitMask.ulMask = PyLong_AsUnsignedLong(ulMask);
  919. break;
  920. case RES_SIZE:
  921. relop = PyObject_GetAttrString(object, "relop");
  922. ulPropTag = PyObject_GetAttrString(object, "ulPropTag");
  923. cb = PyObject_GetAttrString(object, "cb");
  924. if(!relop || !ulPropTag || !cb) {
  925. PyErr_SetString(PyExc_RuntimeError, "relop, ulPropTag or cb missing from RES_SIZE restriction");
  926. goto exit;
  927. }
  928. lpsRestriction->res.resSize.relop = PyLong_AsUnsignedLong(relop);
  929. lpsRestriction->res.resSize.ulPropTag = PyLong_AsUnsignedLong(ulPropTag);
  930. lpsRestriction->res.resSize.cb = PyLong_AsUnsignedLong(cb);
  931. break;
  932. case RES_EXIST:
  933. ulPropTag = PyObject_GetAttrString(object, "ulPropTag");
  934. if(!ulPropTag) {
  935. PyErr_SetString(PyExc_RuntimeError, "ulPropTag missing from RES_EXIST restriction");
  936. goto exit;
  937. }
  938. lpsRestriction->res.resExist.ulPropTag = PyLong_AsUnsignedLong(ulPropTag);
  939. break;
  940. case RES_SUBRESTRICTION:
  941. ulPropTag = PyObject_GetAttrString(object, "ulSubObject");
  942. sub = PyObject_GetAttrString(object, "lpRes");
  943. if(!ulPropTag || !sub) {
  944. PyErr_SetString(PyExc_RuntimeError, "ulSubObject or lpRes missing from RES_SUBRESTRICTION restriction");
  945. goto exit;
  946. }
  947. lpsRestriction->res.resSub.ulSubObject = PyLong_AsUnsignedLong(ulPropTag);
  948. if (MAPIAllocateMore(sizeof(SRestriction), lpBase, (void **)&lpsRestriction->res.resSub.lpRes) != hrSuccess) {
  949. PyErr_SetString(PyExc_RuntimeError, "Out of memory");
  950. goto exit;
  951. }
  952. Object_to_LPSRestriction(sub, lpsRestriction->res.resSub.lpRes, lpBase);
  953. if(PyErr_Occurred())
  954. goto exit;
  955. break;
  956. case RES_COMMENT:
  957. lpProp = PyObject_GetAttrString(object, "lpProp");
  958. sub = PyObject_GetAttrString(object, "lpRes");
  959. if(!lpProp || !sub) {
  960. PyErr_SetString(PyExc_RuntimeError, "lpProp or sub missing from RES_COMMENT restriction");
  961. goto exit;
  962. }
  963. if (MAPIAllocateMore(sizeof(SRestriction), lpBase, (void **)&lpsRestriction->res.resComment.lpRes) != hrSuccess) {
  964. PyErr_SetString(PyExc_RuntimeError, "Out of memory");
  965. goto exit;
  966. }
  967. Object_to_LPSRestriction(sub, lpsRestriction->res.resComment.lpRes, lpBase);
  968. if(PyErr_Occurred())
  969. goto exit;
  970. lpsRestriction->res.resComment.lpProp = List_to_LPSPropValue(lpProp, &lpsRestriction->res.resComment.cValues, CONV_COPY_SHALLOW, lpBase);
  971. break;
  972. default:
  973. PyErr_Format(PyExc_RuntimeError, "Bad restriction type %d", lpsRestriction->rt);
  974. goto exit;
  975. }
  976. exit:
  977. if (lpProp != nullptr)
  978. Py_DECREF(lpProp);
  979. if (ulPropTag2 != nullptr)
  980. Py_DECREF(ulPropTag2);
  981. if (ulPropTag != nullptr)
  982. Py_DECREF(ulPropTag);
  983. if (relop != nullptr)
  984. Py_DECREF(relop);
  985. if (cb != nullptr)
  986. Py_DECREF(cb);
  987. if (ulMask != nullptr)
  988. Py_DECREF(ulMask);
  989. if (ulFuzzyLevel != nullptr)
  990. Py_DECREF(ulFuzzyLevel);
  991. if (rt != nullptr)
  992. Py_DECREF(rt);
  993. if (iter != nullptr)
  994. Py_DECREF(iter);
  995. if (elem != nullptr)
  996. Py_DECREF(elem);
  997. if (sub != nullptr)
  998. Py_DECREF(sub);
  999. }
  1000. LPSRestriction Object_to_LPSRestriction(PyObject *object, void *lpBase)
  1001. {
  1002. LPSRestriction lpRestriction = NULL;
  1003. if(object == Py_None)
  1004. return NULL;
  1005. if (MAPIAllocateBuffer(sizeof(SRestriction), (void **)&lpRestriction) != hrSuccess)
  1006. return NULL;
  1007. Object_to_LPSRestriction(object, lpRestriction);
  1008. if(PyErr_Occurred()) {
  1009. MAPIFreeBuffer(lpRestriction);
  1010. return NULL;
  1011. }
  1012. return lpRestriction;
  1013. }
  1014. PyObject * Object_from_LPSRestriction(LPSRestriction lpsRestriction)
  1015. {
  1016. PyObject *sub = NULL;
  1017. PyObject *subs = NULL;
  1018. PyObject *result = NULL;
  1019. PyObject *propval = NULL;
  1020. PyObject *proplist = NULL;
  1021. if (lpsRestriction == NULL) {
  1022. Py_INCREF(Py_None);
  1023. return Py_None;
  1024. }
  1025. switch(lpsRestriction->rt) {
  1026. case RES_AND:
  1027. case RES_OR:
  1028. subs = PyList_New(0);
  1029. for (ULONG i = 0; i < lpsRestriction->res.resAnd.cRes; ++i) {
  1030. sub = Object_from_LPSRestriction(lpsRestriction->res.resAnd.lpRes + i);
  1031. if (!sub)
  1032. goto exit;
  1033. PyList_Append(subs, sub);
  1034. Py_DECREF(sub);
  1035. sub = NULL;
  1036. }
  1037. if (lpsRestriction->rt == RES_AND)
  1038. result = PyObject_CallFunction(PyTypeSAndRestriction, "O", subs);
  1039. else
  1040. result = PyObject_CallFunction(PyTypeSOrRestriction, "O", subs);
  1041. break;
  1042. case RES_NOT:
  1043. sub = Object_from_LPSRestriction(lpsRestriction->res.resNot.lpRes);
  1044. if(!sub)
  1045. goto exit;
  1046. result = PyObject_CallFunction(PyTypeSNotRestriction, "O", sub);
  1047. break;
  1048. case RES_CONTENT:
  1049. propval = Object_from_LPSPropValue(lpsRestriction->res.resContent.lpProp);
  1050. if (!propval)
  1051. goto exit;
  1052. result = PyObject_CallFunction(PyTypeSContentRestriction, "kkO", lpsRestriction->res.resContent.ulFuzzyLevel, lpsRestriction->res.resContent.ulPropTag, propval);
  1053. break;
  1054. case RES_PROPERTY:
  1055. propval = Object_from_LPSPropValue(lpsRestriction->res.resProperty.lpProp);
  1056. if (!propval)
  1057. goto exit;
  1058. result = PyObject_CallFunction(PyTypeSPropertyRestriction, "kkO", lpsRestriction->res.resProperty.relop, lpsRestriction->res.resProperty.ulPropTag, propval);
  1059. break;
  1060. case RES_COMPAREPROPS:
  1061. result = PyObject_CallFunction(PyTypeSComparePropsRestriction, "kkk", lpsRestriction->res.resCompareProps.relop, lpsRestriction->res.resCompareProps.ulPropTag1, lpsRestriction->res.resCompareProps.ulPropTag2);
  1062. break;
  1063. case RES_BITMASK:
  1064. result = PyObject_CallFunction(PyTypeSBitMaskRestriction, "kkk", lpsRestriction->res.resBitMask.relBMR, lpsRestriction->res.resBitMask.ulPropTag, lpsRestriction->res.resBitMask.ulMask);
  1065. break;
  1066. case RES_SIZE:
  1067. result = PyObject_CallFunction(PyTypeSSizeRestriction, "kkk", lpsRestriction->res.resSize.relop, lpsRestriction->res.resSize.ulPropTag, lpsRestriction->res.resSize.cb);
  1068. break;
  1069. case RES_EXIST:
  1070. result = PyObject_CallFunction(PyTypeSExistRestriction, "k", lpsRestriction->res.resExist.ulPropTag);
  1071. break;
  1072. case RES_SUBRESTRICTION:
  1073. sub = Object_from_LPSRestriction(lpsRestriction->res.resSub.lpRes);
  1074. if (!sub)
  1075. goto exit;
  1076. result = PyObject_CallFunction(PyTypeSSubRestriction, "kO", lpsRestriction->res.resSub.ulSubObject, sub);
  1077. break;
  1078. case RES_COMMENT:
  1079. sub = Object_from_LPSRestriction(lpsRestriction->res.resComment.lpRes);
  1080. if (!sub)
  1081. goto exit;
  1082. proplist = List_from_LPSPropValue(lpsRestriction->res.resComment.lpProp, lpsRestriction->res.resComment.cValues);
  1083. if (!proplist)
  1084. goto exit;
  1085. result = PyObject_CallFunction(PyTypeSCommentRestriction, "OO", sub, proplist);
  1086. break;
  1087. default:
  1088. PyErr_Format(PyExc_RuntimeError, "Bad restriction type %d", lpsRestriction->rt);
  1089. goto exit;
  1090. }
  1091. exit:
  1092. if (sub != nullptr)
  1093. Py_DECREF(sub);
  1094. if (subs != nullptr)
  1095. Py_DECREF(subs);
  1096. if (propval != nullptr)
  1097. Py_DECREF(propval);
  1098. if (proplist != nullptr)
  1099. Py_DECREF(proplist);
  1100. if(PyErr_Occurred()) {
  1101. if (result != nullptr)
  1102. Py_DECREF(result);
  1103. result = NULL;
  1104. }
  1105. return result;
  1106. }
  1107. PyObject * Object_from_LPACTION(LPACTION lpAction)
  1108. {
  1109. PyObject *result = NULL;
  1110. PyObject *act = NULL;
  1111. if (lpAction == NULL) {
  1112. Py_INCREF(Py_None);
  1113. return Py_None;
  1114. }
  1115. switch(lpAction->acttype) {
  1116. case OP_MOVE:
  1117. case OP_COPY:
  1118. act = PyObject_CallFunction(PyTypeActMoveCopy, "s#s#",
  1119. lpAction->actMoveCopy.lpStoreEntryId, lpAction->actMoveCopy.cbStoreEntryId,
  1120. lpAction->actMoveCopy.lpFldEntryId, lpAction->actMoveCopy.cbFldEntryId);
  1121. break;
  1122. case OP_REPLY:
  1123. case OP_OOF_REPLY:
  1124. act = PyObject_CallFunction(PyTypeActReply, "s#s#",
  1125. lpAction->actReply.lpEntryId, lpAction->actReply.cbEntryId,
  1126. &lpAction->actReply.guidReplyTemplate, sizeof(GUID));
  1127. break;
  1128. case OP_DEFER_ACTION:
  1129. act = PyObject_CallFunction(PyTypeActDeferAction, "s#",
  1130. lpAction->actDeferAction.pbData, lpAction->actDeferAction.cbData);
  1131. break;
  1132. case OP_BOUNCE:
  1133. act = PyObject_CallFunction(PyTypeActBounce, "l", lpAction->scBounceCode);
  1134. break;
  1135. case OP_FORWARD:
  1136. case OP_DELEGATE:
  1137. act = PyObject_CallFunction(PyTypeActFwdDelegate, "O", List_from_LPADRLIST(lpAction->lpadrlist));
  1138. break;
  1139. case OP_TAG:
  1140. act = PyObject_CallFunction(PyTypeActTag, "O", Object_from_LPSPropValue(&lpAction->propTag));
  1141. break;
  1142. case OP_DELETE:
  1143. case OP_MARK_AS_READ:
  1144. act = Py_None;
  1145. Py_INCREF(Py_None);
  1146. break;
  1147. };
  1148. // restriction and proptype are always NULL
  1149. Py_INCREF(Py_None);
  1150. Py_INCREF(Py_None);
  1151. result = PyObject_CallFunction(PyTypeAction, "llOOlO", lpAction->acttype, lpAction->ulActionFlavor, Py_None, Py_None, lpAction->ulFlags, act);
  1152. return result;
  1153. }
  1154. PyObject * Object_from_LPACTIONS(ACTIONS *lpsActions)
  1155. {
  1156. PyObject *sub = NULL;
  1157. PyObject *subs = NULL;
  1158. PyObject *result = NULL;
  1159. if (lpsActions == NULL) {
  1160. Py_INCREF(Py_None);
  1161. return Py_None;
  1162. }
  1163. subs = PyList_New(0);
  1164. for (UINT i = 0; i < lpsActions->cActions; ++i) {
  1165. sub = Object_from_LPACTION(&lpsActions->lpAction[i]);
  1166. if (!sub)
  1167. goto exit;
  1168. PyList_Append(subs, sub);
  1169. Py_DECREF(sub);
  1170. sub = NULL;
  1171. }
  1172. result = PyObject_CallFunction(PyTypeACTIONS, "lO", lpsActions->ulVersion, subs);
  1173. exit:
  1174. if (sub != nullptr)
  1175. Py_DECREF(sub);
  1176. if (subs != nullptr)
  1177. Py_DECREF(subs);
  1178. if(PyErr_Occurred()) {
  1179. if (result != nullptr)
  1180. Py_DECREF(result);
  1181. result = NULL;
  1182. }
  1183. return result;
  1184. }
  1185. void Object_to_LPACTION(PyObject *object, ACTION *lpAction, void *lpBase)
  1186. {
  1187. PyObject *poActType = PyObject_GetAttrString(object, "acttype");
  1188. PyObject *poActionFlavor = PyObject_GetAttrString(object, "ulActionFlavor");
  1189. PyObject *poRes = PyObject_GetAttrString(object, "lpRes");
  1190. PyObject *poPropTagArray = PyObject_GetAttrString(object, "lpPropTagArray");
  1191. PyObject *poFlags = PyObject_GetAttrString(object, "ulFlags");
  1192. PyObject *poActObject = PyObject_GetAttrString(object, "actobj");
  1193. lpAction->acttype = (ACTTYPE)PyLong_AsUnsignedLong(poActType);
  1194. lpAction->ulActionFlavor = PyLong_AsUnsignedLong(poActionFlavor);
  1195. // @todo convert (unused) restriction and proptagarray
  1196. lpAction->lpRes = NULL;
  1197. lpAction->lpPropTagArray = NULL;
  1198. lpAction->ulFlags = PyLong_AsUnsignedLong(poFlags);
  1199. lpAction->dwAlignPad = 0;
  1200. switch (lpAction->acttype) {
  1201. case OP_MOVE:
  1202. case OP_COPY:
  1203. {
  1204. PyObject *poStore = PyObject_GetAttrString(poActObject, "StoreEntryId");
  1205. PyObject *poFolder = PyObject_GetAttrString(poActObject, "FldEntryId");
  1206. Py_ssize_t size;
  1207. PyString_AsStringAndSize(poStore, (char**)&lpAction->actMoveCopy.lpStoreEntryId, &size);
  1208. lpAction->actMoveCopy.cbStoreEntryId = size;
  1209. PyString_AsStringAndSize(poFolder, (char**)&lpAction->actMoveCopy.lpFldEntryId, &size);
  1210. lpAction->actMoveCopy.cbFldEntryId = size;
  1211. Py_DECREF(poFolder);
  1212. Py_DECREF(poStore);
  1213. break;
  1214. }
  1215. case OP_REPLY:
  1216. case OP_OOF_REPLY:
  1217. {
  1218. PyObject *poEntryId = PyObject_GetAttrString(poActObject, "EntryId");
  1219. PyObject *poGuid = PyObject_GetAttrString(poActObject, "guidReplyTemplate");
  1220. char *ptr;
  1221. Py_ssize_t size;
  1222. PyString_AsStringAndSize(poEntryId, (char**)&lpAction->actReply.lpEntryId, &size);
  1223. lpAction->actReply.cbEntryId = size;
  1224. PyString_AsStringAndSize(poGuid, &ptr, &size);
  1225. if (size == sizeof(GUID))
  1226. memcpy(&lpAction->actReply.guidReplyTemplate, ptr, size);
  1227. else
  1228. memset(&lpAction->actReply.guidReplyTemplate, 0, sizeof(GUID));
  1229. Py_DECREF(poEntryId);
  1230. Py_DECREF(poGuid);
  1231. break;
  1232. }
  1233. case OP_DEFER_ACTION:
  1234. {
  1235. PyObject *poData = PyObject_GetAttrString(poActObject, "data");
  1236. Py_ssize_t size;
  1237. PyString_AsStringAndSize(poData, (char**)&lpAction->actDeferAction.pbData, &size);
  1238. lpAction->actDeferAction.cbData = size;
  1239. Py_DECREF(poData);
  1240. break;
  1241. }
  1242. case OP_BOUNCE:
  1243. {
  1244. PyObject *poBounce = PyObject_GetAttrString(poActObject, "scBounceCode");
  1245. lpAction->scBounceCode = PyLong_AsUnsignedLong(poBounce);
  1246. Py_DECREF(poBounce);
  1247. break;
  1248. }
  1249. case OP_FORWARD:
  1250. case OP_DELEGATE:
  1251. {
  1252. PyObject *poAdrList = PyObject_GetAttrString(poActObject, "lpadrlist");
  1253. // @todo fix memleak
  1254. lpAction->lpadrlist = List_to_LPADRLIST(poAdrList);
  1255. Py_DECREF(poAdrList);
  1256. break;
  1257. }
  1258. case OP_TAG:
  1259. {
  1260. PyObject *poPropTag = PyObject_GetAttrString(poActObject, "propTag");
  1261. Object_to_LPSPropValue(poPropTag, &lpAction->propTag, CONV_COPY_SHALLOW, lpBase);
  1262. Py_DECREF(poPropTag);
  1263. break;
  1264. }
  1265. case OP_DELETE:
  1266. case OP_MARK_AS_READ:
  1267. break;
  1268. }
  1269. if (poActType != nullptr)
  1270. Py_DECREF(poActType);
  1271. if (poActionFlavor != nullptr)
  1272. Py_DECREF(poActionFlavor);
  1273. if (poRes != nullptr)
  1274. Py_DECREF(poRes);
  1275. if (poPropTagArray != nullptr)
  1276. Py_DECREF(poPropTagArray);
  1277. if (poFlags != nullptr)
  1278. Py_DECREF(poFlags);
  1279. if (poActObject != nullptr)
  1280. Py_DECREF(poActObject);
  1281. }
  1282. void Object_to_LPACTIONS(PyObject *object, ACTIONS *lpActions, void *lpBase)
  1283. {
  1284. HRESULT hr = hrSuccess;
  1285. PyObject *poVersion = NULL;
  1286. PyObject *poAction = NULL;
  1287. PyObject *iter = NULL;
  1288. PyObject *elem = NULL;
  1289. Py_ssize_t len = 0;
  1290. unsigned int i = 0;
  1291. if(object == Py_None)
  1292. goto exit;
  1293. if (lpBase == NULL)
  1294. lpBase = lpActions;
  1295. poVersion = PyObject_GetAttrString(object, "ulVersion");
  1296. poAction = PyObject_GetAttrString(object, "lpAction");
  1297. if(!poVersion || !poAction) {
  1298. PyErr_SetString(PyExc_RuntimeError, "Missing ulVersion or lpAction for ACTIONS struct");
  1299. goto exit;
  1300. }
  1301. len = PyObject_Length(poAction);
  1302. if (len == 0) {
  1303. PyErr_SetString(PyExc_RuntimeError, "No actions found in ACTIONS struct");
  1304. goto exit;
  1305. } else if (len == -1) {
  1306. PyErr_SetString(PyExc_RuntimeError, "No action array found in ACTIONS struct");
  1307. goto exit;
  1308. }
  1309. hr = MAPIAllocateMore(sizeof(ACTION)*len, lpBase, (void**)&lpActions->lpAction);
  1310. if (hr != hrSuccess) {
  1311. PyErr_SetString(PyExc_RuntimeError, "Out of memory");
  1312. goto exit;
  1313. }
  1314. lpActions->ulVersion = PyLong_AsUnsignedLong(poVersion); // EDK_RULES_VERSION
  1315. lpActions->cActions = len;
  1316. iter = PyObject_GetIter(poAction);
  1317. if(iter == NULL)
  1318. goto exit;
  1319. i = 0;
  1320. while ((elem = PyIter_Next(iter))) {
  1321. Object_to_LPACTION(elem, &lpActions->lpAction[i++], lpActions);
  1322. Py_DECREF(elem);
  1323. }
  1324. exit:
  1325. if (poVersion != nullptr)
  1326. Py_DECREF(poVersion);
  1327. if (poAction != nullptr)
  1328. Py_DECREF(poAction);
  1329. if (iter != nullptr)
  1330. Py_DECREF(iter);
  1331. if (elem != nullptr)
  1332. Py_DECREF(elem);
  1333. }
  1334. SSortOrderSet *Object_to_p_SSortOrderSet(PyObject *object)
  1335. {
  1336. PyObject *aSort = NULL;
  1337. PyObject *cCategories = NULL;
  1338. PyObject *cExpanded = NULL;
  1339. PyObject *iter = NULL;
  1340. PyObject *elem = NULL;
  1341. PyObject *ulPropTag = NULL;
  1342. PyObject *ulOrder = NULL;
  1343. SSortOrderSet *lpsSortOrderSet = NULL;
  1344. Py_ssize_t len = 0;
  1345. unsigned int i = 0;
  1346. if(object == Py_None)
  1347. goto exit;
  1348. aSort = PyObject_GetAttrString(object, "aSort");
  1349. cCategories = PyObject_GetAttrString(object, "cCategories");
  1350. cExpanded = PyObject_GetAttrString(object, "cExpanded");
  1351. if(!aSort || !cCategories || !cExpanded) {
  1352. PyErr_SetString(PyExc_RuntimeError, "Missing aSort, cCategories or cExpanded for sort order");
  1353. goto exit;
  1354. }
  1355. len = PyObject_Length(aSort);
  1356. if(len < 0) {
  1357. PyErr_SetString(PyExc_RuntimeError, "aSort is not a sequence");
  1358. goto exit;
  1359. }
  1360. if (MAPIAllocateBuffer(CbNewSSortOrderSet(len), (void **)&lpsSortOrderSet) != hrSuccess)
  1361. goto exit;
  1362. iter = PyObject_GetIter(aSort);
  1363. if(iter == NULL)
  1364. goto exit;
  1365. while((elem = PyIter_Next(iter))) {
  1366. ulOrder = PyObject_GetAttrString(elem, "ulOrder");
  1367. ulPropTag = PyObject_GetAttrString(elem, "ulPropTag");
  1368. if(!ulOrder || !ulPropTag) {
  1369. PyErr_SetString(PyExc_RuntimeError, "ulOrder or ulPropTag missing for sort order");
  1370. goto exit;
  1371. }
  1372. lpsSortOrderSet->aSort[i].ulOrder = PyLong_AsUnsignedLong(ulOrder);
  1373. lpsSortOrderSet->aSort[i].ulPropTag = PyLong_AsUnsignedLong(ulPropTag);
  1374. ++i;
  1375. Py_DECREF(elem);
  1376. }
  1377. lpsSortOrderSet->cSorts = i;
  1378. lpsSortOrderSet->cCategories = PyLong_AsUnsignedLong(cCategories);
  1379. lpsSortOrderSet->cExpanded = PyLong_AsUnsignedLong(cExpanded);
  1380. exit:
  1381. if(PyErr_Occurred()) {
  1382. MAPIFreeBuffer(lpsSortOrderSet);
  1383. lpsSortOrderSet = NULL;
  1384. }
  1385. if (ulOrder != nullptr)
  1386. Py_DECREF(ulOrder);
  1387. if (ulPropTag != nullptr)
  1388. Py_DECREF(ulPropTag);
  1389. if (iter != nullptr)
  1390. Py_DECREF(iter);
  1391. if (elem != nullptr)
  1392. Py_DECREF(elem);
  1393. if (aSort != nullptr)
  1394. Py_DECREF(aSort);
  1395. if (cCategories != nullptr)
  1396. Py_DECREF(cCategories);
  1397. if (cExpanded != nullptr)
  1398. Py_DECREF(cExpanded);
  1399. return lpsSortOrderSet;
  1400. }
  1401. PyObject *Object_from_SSortOrderSet(const SSortOrderSet *lpSortOrderSet)
  1402. {
  1403. PyObject *sort = NULL;
  1404. PyObject *sorts = NULL;
  1405. PyObject *result = NULL;
  1406. if(lpSortOrderSet == NULL) {
  1407. Py_INCREF(Py_None);
  1408. return Py_None;
  1409. }
  1410. sorts = PyList_New(0);
  1411. for (unsigned int i = 0; i < lpSortOrderSet->cSorts; ++i) {
  1412. sort = PyObject_CallFunction(PyTypeSSort, "(ll)", lpSortOrderSet->aSort[i].ulPropTag, lpSortOrderSet->aSort[i].ulOrder);
  1413. if(PyErr_Occurred())
  1414. goto exit;
  1415. PyList_Append(sorts,sort);
  1416. Py_DECREF(sort);
  1417. sort = NULL;
  1418. }
  1419. result = PyObject_CallFunction(PyTypeSSortOrderSet, "(Oll)", sorts, lpSortOrderSet->cCategories, lpSortOrderSet->cExpanded);
  1420. exit:
  1421. if (sorts != nullptr)
  1422. Py_DECREF(sorts);
  1423. if (sort != nullptr)
  1424. Py_DECREF(sort);
  1425. if(PyErr_Occurred()) {
  1426. if (result != nullptr)
  1427. Py_DECREF(result);
  1428. result = NULL;
  1429. }
  1430. return result;
  1431. }
  1432. PyObject *List_from_SRowSet(const SRowSet *lpRowSet)
  1433. {
  1434. PyObject *list = PyList_New(0);
  1435. PyObject *item = NULL;
  1436. for (unsigned int i = 0; i < lpRowSet->cRows; ++i) {
  1437. item = List_from_LPSPropValue(lpRowSet->aRow[i].lpProps, lpRowSet->aRow[i].cValues);
  1438. if(PyErr_Occurred())
  1439. goto exit;
  1440. PyList_Append(list, item);
  1441. Py_DECREF(item);
  1442. item = NULL;
  1443. }
  1444. exit:
  1445. if (item != nullptr)
  1446. Py_DECREF(item);
  1447. if(PyErr_Occurred()) {
  1448. if (list != nullptr)
  1449. Py_DECREF(list);
  1450. list = NULL;
  1451. }
  1452. return list;
  1453. }
  1454. PyObject *List_from_LPSRowSet(const SRowSet *s)
  1455. {
  1456. return List_from_SRowSet(s);
  1457. }
  1458. SRowSet *List_to_p_SRowSet(PyObject *list, ULONG ulFlags)
  1459. {
  1460. PyObject *iter = NULL;
  1461. PyObject *elem = NULL;
  1462. Py_ssize_t len = 0;
  1463. LPSRowSet lpsRowSet = NULL;
  1464. int i = 0;
  1465. if (list == Py_None)
  1466. goto exit;
  1467. len = PyObject_Length(list);
  1468. iter = PyObject_GetIter(list);
  1469. if(!iter)
  1470. goto exit;
  1471. // Zero out the whole struct so that failures halfway don't leave the struct
  1472. // in an uninitialized state for FreeProws()
  1473. if (MAPIAllocateBuffer(CbNewSRowSet(len), (void **)&lpsRowSet) != hrSuccess)
  1474. goto exit;
  1475. memset(lpsRowSet, 0, CbNewSRowSet(len));
  1476. while((elem = PyIter_Next(iter))) {
  1477. lpsRowSet->aRow[i].lpProps = List_to_LPSPropValue(elem, &lpsRowSet->aRow[i].cValues, ulFlags);
  1478. if(PyErr_Occurred())
  1479. goto exit;
  1480. Py_DECREF(elem);
  1481. elem = NULL;
  1482. ++i;
  1483. }
  1484. lpsRowSet->cRows = i;
  1485. exit:
  1486. if (elem != nullptr)
  1487. Py_DECREF(elem);
  1488. if (iter != nullptr)
  1489. Py_DECREF(iter);
  1490. if(PyErr_Occurred()) {
  1491. if(lpsRowSet)
  1492. FreeProws(lpsRowSet);
  1493. lpsRowSet = NULL;
  1494. }
  1495. return lpsRowSet;
  1496. }
  1497. SRowSet *List_to_LPSRowSet(PyObject *obj, ULONG flags)
  1498. {
  1499. return List_to_p_SRowSet(obj, flags);
  1500. }
  1501. ADRLIST *List_to_p_ADRLIST(PyObject *av, ULONG ulFlags)
  1502. {
  1503. // Binary compatible
  1504. return (LPADRLIST) List_to_LPSRowSet(av, ulFlags);
  1505. }
  1506. ADRLIST *List_to_LPADRLIST(PyObject *av, ULONG ulFlags)
  1507. {
  1508. // Binary compatible
  1509. return (LPADRLIST) List_to_LPSRowSet(av, ulFlags);
  1510. }
  1511. PyObject *List_from_ADRLIST(const ADRLIST *lpAdrList)
  1512. {
  1513. // Binary compatible
  1514. return List_from_LPSRowSet((LPSRowSet)lpAdrList);
  1515. }
  1516. PyObject *List_from_LPADRLIST(const ADRLIST *lpAdrList)
  1517. {
  1518. // Binary compatible
  1519. return List_from_LPSRowSet((LPSRowSet)lpAdrList);
  1520. }
  1521. LPADRPARM Object_to_LPADRPARM(PyObject *av)
  1522. {
  1523. // Unsupported for now
  1524. PyErr_SetString(PyExc_RuntimeError, "LPADRPARM is not yet supported");
  1525. return NULL;
  1526. }
  1527. LPADRENTRY Object_to_LPADRENTRY(PyObject *av)
  1528. {
  1529. // Unsupported for now
  1530. PyErr_SetString(PyExc_RuntimeError, "LPADRENTRY is not yet supported");
  1531. return NULL;
  1532. }
  1533. PyObject * Object_from_LPSPropProblem(LPSPropProblem lpProblem)
  1534. {
  1535. return PyObject_CallFunction(PyTypeSPropProblem, "(lII)", lpProblem->ulIndex, lpProblem->ulPropTag, lpProblem->scode);
  1536. }
  1537. void Object_to_LPSPropProblem(PyObject *object, LPSPropProblem lpProblem)
  1538. {
  1539. PyObject *scode = NULL;
  1540. PyObject *ulIndex = NULL;
  1541. PyObject *ulPropTag = NULL;
  1542. scode = PyObject_GetAttrString(object, "scode");
  1543. ulIndex = PyObject_GetAttrString(object, "ulIndex");
  1544. ulPropTag = PyObject_GetAttrString(object, "ulPropTag");
  1545. lpProblem->scode = PyLong_AsUnsignedLong(scode);
  1546. lpProblem->ulIndex = PyLong_AsUnsignedLong(ulIndex);
  1547. lpProblem->ulPropTag = PyLong_AsUnsignedLong(ulPropTag);
  1548. if(scode)
  1549. Py_DECREF(scode);
  1550. if(ulIndex)
  1551. Py_DECREF(ulIndex);
  1552. if(ulPropTag)
  1553. Py_DECREF(ulPropTag);
  1554. }
  1555. PyObject * List_from_LPSPropProblemArray(LPSPropProblemArray lpProblemArray)
  1556. {
  1557. PyObject *list = NULL;
  1558. PyObject *elem = NULL;
  1559. if(lpProblemArray == NULL) {
  1560. Py_INCREF(Py_None);
  1561. list = Py_None;
  1562. goto exit;
  1563. }
  1564. list = PyList_New(0);
  1565. for (unsigned int i = 0; i < lpProblemArray->cProblem; ++i) {
  1566. elem = Object_from_LPSPropProblem(&lpProblemArray->aProblem[i]);
  1567. if(PyErr_Occurred())
  1568. goto exit;
  1569. PyList_Append(list, elem);
  1570. Py_DECREF(elem);
  1571. elem = NULL;
  1572. }
  1573. exit:
  1574. if(PyErr_Occurred()) {
  1575. if (list != nullptr)
  1576. Py_DECREF(list);
  1577. list = NULL;
  1578. }
  1579. if (elem != nullptr)
  1580. Py_DECREF(elem);
  1581. return list;
  1582. }
  1583. LPSPropProblemArray List_to_LPSPropProblemArray(PyObject *list, ULONG /*ulFlags*/)
  1584. {
  1585. PyObject *iter = NULL;
  1586. PyObject *elem = NULL;
  1587. Py_ssize_t len = 0;
  1588. LPSPropProblemArray lpsProblems = NULL;
  1589. int i = 0;
  1590. if (list == Py_None)
  1591. goto exit;
  1592. len = PyObject_Length(list);
  1593. iter = PyObject_GetIter(list);
  1594. if(!iter)
  1595. goto exit;
  1596. if (MAPIAllocateBuffer(CbNewSPropProblemArray(len), (void **)&lpsProblems) != hrSuccess)
  1597. goto exit;
  1598. memset(lpsProblems, 0, CbNewSPropProblemArray(len));
  1599. while((elem = PyIter_Next(iter))) {
  1600. Object_to_LPSPropProblem(elem, &lpsProblems->aProblem[i]);
  1601. if(PyErr_Occurred())
  1602. goto exit;
  1603. Py_DECREF(elem);
  1604. elem = NULL;
  1605. ++i;
  1606. }
  1607. lpsProblems->cProblem = i;
  1608. exit:
  1609. if (elem != nullptr)
  1610. Py_DECREF(elem);
  1611. if (iter != nullptr)
  1612. Py_DECREF(iter);
  1613. if(PyErr_Occurred()) {
  1614. MAPIFreeBuffer(lpsProblems);
  1615. lpsProblems = NULL;
  1616. }
  1617. return lpsProblems;
  1618. }
  1619. PyObject * Object_from_LPMAPINAMEID(LPMAPINAMEID lpMAPINameId)
  1620. {
  1621. PyObject *elem = NULL;
  1622. PyObject *guid = NULL;
  1623. if(lpMAPINameId == NULL) {
  1624. Py_INCREF(Py_None);
  1625. return Py_None;
  1626. }
  1627. guid = PyString_FromStringAndSize((char *)lpMAPINameId->lpguid, sizeof(GUID));
  1628. if(lpMAPINameId->ulKind == MNID_ID)
  1629. elem = PyObject_CallFunction(PyTypeMAPINAMEID, "(Oll)", guid, MNID_ID, lpMAPINameId->Kind.lID);
  1630. else
  1631. elem = PyObject_CallFunction(PyTypeMAPINAMEID, "(Olu)", guid, MNID_STRING, lpMAPINameId->Kind.lpwstrName);
  1632. if (guid != nullptr)
  1633. Py_DECREF(guid);
  1634. return elem;
  1635. }
  1636. PyObject * List_from_LPMAPINAMEID(LPMAPINAMEID *lppMAPINameId, ULONG cNames)
  1637. {
  1638. PyObject *list = NULL;
  1639. PyObject *elem = NULL;
  1640. list = PyList_New(0);
  1641. for (unsigned int i = 0; i < cNames; ++i) {
  1642. elem = Object_from_LPMAPINAMEID(lppMAPINameId[i]);
  1643. if(PyErr_Occurred())
  1644. goto exit;
  1645. PyList_Append(list, elem);
  1646. Py_DECREF(elem);
  1647. elem = NULL;
  1648. }
  1649. exit:
  1650. if(PyErr_Occurred()) {
  1651. Py_DECREF(list);
  1652. list = NULL;
  1653. }
  1654. if (elem != nullptr)
  1655. Py_DECREF(elem);
  1656. return list;
  1657. }
  1658. void Object_to_LPMAPINAMEID(PyObject *elem, LPMAPINAMEID *lppName, void *lpBase)
  1659. {
  1660. LPMAPINAMEID lpName = NULL;
  1661. PyObject *kind = NULL;
  1662. PyObject *id = NULL;
  1663. PyObject *guid = NULL;
  1664. ULONG ulKind = 0;
  1665. Py_ssize_t len = 0;
  1666. if (MAPIAllocateMore(sizeof(MAPINAMEID), lpBase, (void **)&lpName) != hrSuccess) {
  1667. PyErr_SetString(PyExc_RuntimeError, "Out of memory");
  1668. goto exit;
  1669. }
  1670. memset(lpName, 0, sizeof(MAPINAMEID));
  1671. kind = PyObject_GetAttrString(elem, "kind");
  1672. id = PyObject_GetAttrString(elem, "id");
  1673. guid = PyObject_GetAttrString(elem, "guid");
  1674. if(!guid || !id) {
  1675. PyErr_SetString(PyExc_RuntimeError, "Missing id or guid on MAPINAMEID object");
  1676. goto exit;
  1677. }
  1678. if(!kind) {
  1679. // Detect kind from type of 'id' parameter by first trying to use it as an int, then as string
  1680. PyInt_AsLong(id);
  1681. if(PyErr_Occurred()) {
  1682. // Clear error
  1683. PyErr_Clear();
  1684. ulKind = MNID_STRING;
  1685. } else {
  1686. ulKind = MNID_ID;
  1687. }
  1688. } else {
  1689. ulKind = PyInt_AsLong(kind);
  1690. }
  1691. lpName->ulKind = ulKind;
  1692. if(ulKind == MNID_ID) {
  1693. lpName->Kind.lID = PyInt_AsLong(id);
  1694. } else {
  1695. if(!PyUnicode_Check(id)) {
  1696. PyErr_SetString(PyExc_RuntimeError, "Must pass unicode string for MNID_STRING ID part of MAPINAMEID");
  1697. goto exit;
  1698. }
  1699. CopyPyUnicode(&lpName->Kind.lpwstrName, id, lpBase);
  1700. }
  1701. if (PyString_AsStringAndSize(guid, reinterpret_cast<char **>(&lpName->lpguid), &len) == -1)
  1702. goto exit;
  1703. if(len != sizeof(GUID)) {
  1704. PyErr_Format(PyExc_RuntimeError, "GUID parameter of MAPINAMEID must be exactly %d bytes", (int)sizeof(GUID));
  1705. goto exit;
  1706. }
  1707. *lppName = lpName;
  1708. exit:
  1709. if (PyErr_Occurred() && lpBase == nullptr)
  1710. MAPIFreeBuffer(lpName);
  1711. if (guid != nullptr)
  1712. Py_DECREF(guid);
  1713. if (id != nullptr)
  1714. Py_DECREF(id);
  1715. if (kind != nullptr)
  1716. Py_DECREF(kind);
  1717. }
  1718. LPMAPINAMEID * List_to_p_LPMAPINAMEID(PyObject *list, ULONG *lpcNames, ULONG /*ulFlags*/)
  1719. {
  1720. LPMAPINAMEID *lpNames = NULL;
  1721. Py_ssize_t len = 0;
  1722. PyObject *iter = NULL;
  1723. PyObject *elem = NULL;
  1724. unsigned int i = 0;
  1725. iter = PyObject_GetIter(list);
  1726. if(!iter)
  1727. goto exit;
  1728. len = PyObject_Length(list);
  1729. if (MAPIAllocateBuffer(sizeof(LPMAPINAMEID) * len, (void **)&lpNames) != hrSuccess)
  1730. goto exit;
  1731. memset(lpNames, 0, sizeof(LPMAPINAMEID) * len);
  1732. while((elem = PyIter_Next(iter))) {
  1733. Object_to_LPMAPINAMEID(elem, &lpNames[i], lpNames);
  1734. if(PyErr_Occurred())
  1735. goto exit;
  1736. ++i;
  1737. Py_DECREF(elem);
  1738. elem = NULL;
  1739. }
  1740. *lpcNames = i;
  1741. exit:
  1742. if(PyErr_Occurred()) {
  1743. MAPIFreeBuffer(lpNames);
  1744. lpNames = NULL;
  1745. }
  1746. if (elem != nullptr)
  1747. Py_DECREF(elem);
  1748. if (iter != nullptr)
  1749. Py_DECREF(iter);
  1750. return lpNames;
  1751. }
  1752. LPENTRYLIST List_to_LPENTRYLIST(PyObject *list)
  1753. {
  1754. LPENTRYLIST lpEntryList = NULL;
  1755. Py_ssize_t len = 0;
  1756. PyObject *iter = NULL;
  1757. PyObject *elem = NULL;
  1758. unsigned int i = 0;
  1759. if(list == Py_None)
  1760. return NULL;
  1761. iter = PyObject_GetIter(list);
  1762. if(!iter)
  1763. goto exit;
  1764. len = PyObject_Length(list);
  1765. if (MAPIAllocateBuffer(sizeof(*lpEntryList), (void **)&lpEntryList) != hrSuccess)
  1766. goto exit;
  1767. if (MAPIAllocateMore(len * sizeof *lpEntryList->lpbin, lpEntryList, (void**)&lpEntryList->lpbin) != hrSuccess)
  1768. goto exit;
  1769. lpEntryList->cValues = len;
  1770. while((elem = PyIter_Next(iter))) {
  1771. char *ptr;
  1772. Py_ssize_t strlen;
  1773. if (PyString_AsStringAndSize(elem, &ptr, &strlen) == -1 ||
  1774. PyErr_Occurred())
  1775. goto exit;
  1776. lpEntryList->lpbin[i].cb = strlen;
  1777. if (MAPIAllocateMore(strlen, lpEntryList, (void**)&lpEntryList->lpbin[i].lpb) != hrSuccess)
  1778. goto exit;
  1779. memcpy(lpEntryList->lpbin[i].lpb, ptr, strlen);
  1780. ++i;
  1781. Py_DECREF(elem);
  1782. elem = NULL;
  1783. }
  1784. exit:
  1785. if(PyErr_Occurred()) {
  1786. MAPIFreeBuffer(lpEntryList);
  1787. lpEntryList = NULL;
  1788. }
  1789. if (elem != nullptr)
  1790. Py_DECREF(elem);
  1791. if (iter != nullptr)
  1792. Py_DECREF(iter);
  1793. return lpEntryList;
  1794. }
  1795. PyObject * List_from_LPENTRYLIST(LPENTRYLIST lpEntryList)
  1796. {
  1797. PyObject *list = NULL;
  1798. PyObject *elem = NULL;
  1799. list = PyList_New(0);
  1800. if (lpEntryList) {
  1801. for (unsigned int i = 0; i < lpEntryList->cValues; ++i) {
  1802. elem = PyString_FromStringAndSize((const char*)lpEntryList->lpbin[i].lpb, lpEntryList->lpbin[i].cb);
  1803. if(PyErr_Occurred())
  1804. goto exit;
  1805. PyList_Append(list, elem);
  1806. Py_DECREF(elem);
  1807. elem = NULL;
  1808. }
  1809. }
  1810. exit:
  1811. if(PyErr_Occurred()) {
  1812. Py_DECREF(list);
  1813. list = NULL;
  1814. }
  1815. if (elem != nullptr)
  1816. Py_DECREF(elem);
  1817. return list;
  1818. }
  1819. LPNOTIFICATION List_to_LPNOTIFICATION(PyObject *, ULONG *lpcNotifs)
  1820. {
  1821. return NULL;
  1822. }
  1823. PyObject * List_from_LPNOTIFICATION(LPNOTIFICATION lpNotif, ULONG cNotifs)
  1824. {
  1825. PyObject *list = PyList_New(0);
  1826. PyObject *item = NULL;
  1827. for (unsigned int i = 0; i < cNotifs; ++i) {
  1828. item = Object_from_LPNOTIFICATION(&lpNotif[i]);
  1829. if(PyErr_Occurred())
  1830. goto exit;
  1831. PyList_Append(list, item);
  1832. Py_DECREF(item);
  1833. item = NULL;
  1834. }
  1835. exit:
  1836. if(PyErr_Occurred()) {
  1837. if (list != nullptr)
  1838. Py_DECREF(list);
  1839. list = NULL;
  1840. }
  1841. if (item != nullptr)
  1842. Py_DECREF(item);
  1843. return list;
  1844. }
  1845. PyObject * Object_from_LPNOTIFICATION(NOTIFICATION *lpNotif)
  1846. {
  1847. PyObject *elem = NULL;
  1848. PyObject *proptags = NULL;
  1849. PyObject *index = NULL;
  1850. PyObject *prior = NULL;
  1851. PyObject *row = NULL;
  1852. if(lpNotif == NULL) {
  1853. Py_INCREF(Py_None);
  1854. return Py_None;
  1855. }
  1856. switch(lpNotif->ulEventType) {
  1857. case fnevObjectCopied:
  1858. case fnevObjectCreated:
  1859. case fnevObjectDeleted:
  1860. case fnevObjectModified:
  1861. case fnevObjectMoved:
  1862. case fnevSearchComplete:
  1863. proptags = List_from_LPSPropTagArray(lpNotif->info.obj.lpPropTagArray);
  1864. if (!proptags)
  1865. return NULL;
  1866. elem = PyObject_CallFunction(PyTypeOBJECT_NOTIFICATION, "(ls#ls#s#s#O)",
  1867. lpNotif->ulEventType,
  1868. lpNotif->info.obj.lpEntryID, lpNotif->info.obj.cbEntryID,
  1869. lpNotif->info.obj.ulObjType,
  1870. lpNotif->info.obj.lpParentID, lpNotif->info.obj.cbParentID,
  1871. lpNotif->info.obj.lpOldID, lpNotif->info.obj.cbOldID,
  1872. lpNotif->info.obj.lpOldParentID, lpNotif->info.obj.cbOldParentID,
  1873. proptags);
  1874. Py_DECREF(proptags);
  1875. break;
  1876. case fnevTableModified:
  1877. index = Object_from_LPSPropValue(&lpNotif->info.tab.propIndex);
  1878. if (!index)
  1879. return NULL;
  1880. prior = Object_from_LPSPropValue(&lpNotif->info.tab.propPrior);
  1881. if (!prior)
  1882. return NULL;
  1883. row = List_from_LPSPropValue(lpNotif->info.tab.row.lpProps, lpNotif->info.tab.row.cValues);
  1884. if (!row)
  1885. return NULL;
  1886. elem = PyObject_CallFunction(PyTypeTABLE_NOTIFICATION, "(lIOOO)", lpNotif->info.tab.ulTableEvent, lpNotif->info.tab.hResult, index, prior, row);
  1887. Py_DECREF(index);
  1888. Py_DECREF(prior);
  1889. Py_DECREF(row);
  1890. break;
  1891. case fnevNewMail:
  1892. elem = PyObject_CallFunction(PyTypeNEWMAIL_NOTIFICATION, "(s#s#lsl)", lpNotif->info.newmail.lpEntryID, lpNotif->info.newmail.cbEntryID,
  1893. lpNotif->info.newmail.lpParentID, lpNotif->info.newmail.cbParentID,
  1894. lpNotif->info.newmail.ulFlags,
  1895. lpNotif->info.newmail.lpszMessageClass,
  1896. lpNotif->info.newmail.ulMessageFlags);
  1897. break;
  1898. default:
  1899. PyErr_Format(PyExc_RuntimeError, "Bad notification type %x", lpNotif->ulEventType);
  1900. break;
  1901. }
  1902. return elem;
  1903. }
  1904. NOTIFICATION * Object_to_LPNOTIFICATION(PyObject *obj)
  1905. {
  1906. PyObject *oTmp = NULL;
  1907. LPNOTIFICATION lpNotif = NULL;
  1908. if(obj == Py_None)
  1909. return NULL;
  1910. if (MAPIAllocateBuffer(sizeof(NOTIFICATION), (void**)&lpNotif) != hrSuccess)
  1911. goto exit;
  1912. memset(lpNotif, 0, sizeof(NOTIFICATION));
  1913. if(PyObject_IsInstance(obj, PyTypeNEWMAIL_NOTIFICATION))
  1914. {
  1915. lpNotif->ulEventType = fnevNewMail;
  1916. Py_ssize_t size;
  1917. oTmp = PyObject_GetAttrString(obj, "lpEntryID");
  1918. if(!oTmp) {
  1919. PyErr_SetString(PyExc_RuntimeError, "lpEntryID missing for newmail notification");
  1920. goto exit;
  1921. }
  1922. if (oTmp != Py_None) {
  1923. PyString_AsStringAndSize(oTmp, (char**)&lpNotif->info.newmail.lpEntryID, &size);
  1924. lpNotif->info.newmail.cbEntryID = size;
  1925. }
  1926. Py_DECREF(oTmp);
  1927. oTmp = PyObject_GetAttrString(obj, "lpParentID");
  1928. if(!oTmp) {
  1929. PyErr_SetString(PyExc_RuntimeError, "lpParentID missing for newmail notification");
  1930. goto exit;
  1931. }
  1932. if (oTmp != Py_None) {
  1933. PyString_AsStringAndSize(oTmp, (char**)&lpNotif->info.newmail.lpParentID, &size);
  1934. lpNotif->info.newmail.cbParentID = size;
  1935. }
  1936. Py_DECREF(oTmp);
  1937. oTmp = PyObject_GetAttrString(obj, "ulFlags");
  1938. if(!oTmp) {
  1939. PyErr_SetString(PyExc_RuntimeError, "ulFlags missing for newmail notification");
  1940. goto exit;
  1941. }
  1942. if (oTmp != Py_None) {
  1943. lpNotif->info.newmail.ulFlags = (ULONG)PyLong_AsUnsignedLong(oTmp);
  1944. }
  1945. Py_DECREF(oTmp);
  1946. oTmp = PyObject_GetAttrString(obj, "ulMessageFlags");
  1947. if(!oTmp) {
  1948. PyErr_SetString(PyExc_RuntimeError, "ulMessageFlags missing for newmail notification");
  1949. goto exit;
  1950. }
  1951. if (oTmp != Py_None) {
  1952. lpNotif->info.newmail.ulMessageFlags = (ULONG)PyLong_AsUnsignedLong(oTmp);
  1953. }
  1954. Py_DECREF(oTmp);
  1955. // MessageClass
  1956. oTmp= PyObject_GetAttrString(obj, "lpszMessageClass");
  1957. if(!oTmp) {
  1958. PyErr_SetString(PyExc_RuntimeError, "lpszMessageClass missing for newmail notification");
  1959. goto exit;
  1960. }
  1961. if (oTmp != Py_None) {
  1962. if (lpNotif->info.newmail.ulFlags & MAPI_UNICODE)
  1963. CopyPyUnicode(&lpNotif->info.newmail.lpszMessageClass, oTmp, lpNotif);
  1964. else if (PyString_AsStringAndSize(oTmp, reinterpret_cast<char **>(&lpNotif->info.newmail.lpszMessageClass), nullptr) == -1)
  1965. goto exit;
  1966. }
  1967. Py_DECREF(oTmp);
  1968. oTmp = NULL;
  1969. } else {
  1970. PyErr_Format(PyExc_RuntimeError, "Bad object type %p", obj->ob_type);
  1971. }
  1972. exit:
  1973. if(PyErr_Occurred()) {
  1974. MAPIFreeBuffer(lpNotif);
  1975. lpNotif = NULL;
  1976. }
  1977. if(oTmp)
  1978. Py_DECREF(oTmp);
  1979. return lpNotif;
  1980. }
  1981. LPFlagList List_to_LPFlagList(PyObject *list)
  1982. {
  1983. PyObject *iter = NULL;
  1984. PyObject *elem = NULL;
  1985. Py_ssize_t len = 0;
  1986. LPFlagList lpList = NULL;
  1987. int i = 0;
  1988. iter = PyObject_GetIter(list);
  1989. if(!iter)
  1990. goto exit;
  1991. len = PyObject_Length(list);
  1992. if (MAPIAllocateBuffer(CbNewFlagList(len), (void **)&lpList) != hrSuccess)
  1993. goto exit;
  1994. while((elem = PyIter_Next(iter))) {
  1995. lpList->ulFlag[i] = PyLong_AsUnsignedLong(elem);
  1996. if(PyErr_Occurred())
  1997. goto exit;
  1998. ++i;
  1999. Py_DECREF(elem);
  2000. elem = NULL;
  2001. }
  2002. lpList->cFlags = i;
  2003. exit:
  2004. if(PyErr_Occurred()) {
  2005. MAPIFreeBuffer(lpList);
  2006. lpList = NULL;
  2007. }
  2008. if (elem != nullptr)
  2009. Py_DECREF(elem);
  2010. if (iter != nullptr)
  2011. Py_DECREF(iter);
  2012. return lpList;
  2013. }
  2014. PyObject * List_from_LPFlagList(LPFlagList lpFlags)
  2015. {
  2016. PyObject *list = PyList_New(0);
  2017. PyObject *elem = NULL;
  2018. for (unsigned int i = 0; i < lpFlags->cFlags; ++i) {
  2019. elem = PyLong_FromUnsignedLong(lpFlags->ulFlag[i]);
  2020. PyList_Append(list, elem);
  2021. Py_DECREF(elem);
  2022. elem = NULL;
  2023. }
  2024. return list;
  2025. }
  2026. PyObject * Object_from_LPMAPIERROR(LPMAPIERROR lpMAPIError)
  2027. {
  2028. Py_INCREF(Py_None);
  2029. return Py_None;
  2030. }
  2031. LPMAPIERROR Object_to_LPMAPIERROR(PyObject *)
  2032. {
  2033. LPMAPIERROR lpError = NULL;
  2034. if (MAPIAllocateBuffer(sizeof(LPMAPIERROR), (LPVOID*)&lpError) == hrSuccess)
  2035. memset(lpError, 0, sizeof(*lpError));
  2036. return lpError;
  2037. }
  2038. LPREADSTATE List_to_LPREADSTATE(PyObject *list, ULONG *lpcElements)
  2039. {
  2040. PyObject *iter = NULL;
  2041. PyObject *elem = NULL;
  2042. PyObject *sourcekey = NULL;
  2043. PyObject *flags = NULL;
  2044. Py_ssize_t len = 0;
  2045. LPREADSTATE lpList = NULL;
  2046. int i = 0;
  2047. iter = PyObject_GetIter(list);
  2048. if(!iter)
  2049. goto exit;
  2050. len = PyObject_Length(list);
  2051. if (MAPIAllocateBuffer(len * sizeof *lpList, (void **)&lpList) != hrSuccess)
  2052. goto exit;
  2053. while((elem = PyIter_Next(iter))) {
  2054. HRESULT hr;
  2055. sourcekey = PyObject_GetAttrString(elem, "SourceKey");
  2056. flags = PyObject_GetAttrString(elem, "ulFlags");
  2057. if (!sourcekey || !flags)
  2058. continue;
  2059. char *ptr = NULL;
  2060. Py_ssize_t len = 0;
  2061. lpList[i].ulFlags = PyLong_AsUnsignedLong(flags);
  2062. if (PyErr_Occurred())
  2063. goto exit;
  2064. if (PyString_AsStringAndSize(sourcekey, &ptr, &len) == -1 ||
  2065. PyErr_Occurred())
  2066. goto exit;
  2067. hr = MAPIAllocateMore(len, lpList, (LPVOID*)&lpList[i].pbSourceKey);
  2068. if (hr != hrSuccess) {
  2069. PyErr_SetString(PyExc_RuntimeError, "Out of memory");
  2070. goto exit;
  2071. }
  2072. memcpy(lpList[i].pbSourceKey, ptr, len);
  2073. lpList[i].cbSourceKey = len;
  2074. ++i;
  2075. Py_DECREF(flags);
  2076. flags = NULL;
  2077. Py_DECREF(sourcekey);
  2078. sourcekey = NULL;
  2079. Py_DECREF(elem);
  2080. elem = NULL;
  2081. }
  2082. *lpcElements = len;
  2083. exit:
  2084. if(PyErr_Occurred()) {
  2085. MAPIFreeBuffer(lpList);
  2086. lpList = NULL;
  2087. }
  2088. if (flags != nullptr)
  2089. Py_DECREF(flags);
  2090. if (sourcekey != nullptr)
  2091. Py_DECREF(sourcekey);
  2092. if (elem != nullptr)
  2093. Py_DECREF(elem);
  2094. if (iter != nullptr)
  2095. Py_DECREF(iter);
  2096. return lpList;
  2097. }
  2098. PyObject * List_from_LPREADSTATE(LPREADSTATE lpReadState, ULONG cElements)
  2099. {
  2100. PyObject *list = PyList_New(0);
  2101. PyObject *elem = NULL;
  2102. PyObject *sourcekey = NULL;
  2103. for (unsigned int i = 0; i < cElements; ++i) {
  2104. sourcekey = PyString_FromStringAndSize((char*)lpReadState[i].pbSourceKey, lpReadState[i].cbSourceKey);
  2105. if (PyErr_Occurred())
  2106. goto exit;
  2107. elem = PyObject_CallFunction(PyTypeREADSTATE, "(Ol)", sourcekey, lpReadState[i].ulFlags);
  2108. if (PyErr_Occurred())
  2109. goto exit;
  2110. PyList_Append(list, elem);
  2111. Py_DECREF(sourcekey);
  2112. sourcekey = NULL;
  2113. Py_DECREF(elem);
  2114. elem = NULL;
  2115. }
  2116. exit:
  2117. if (PyErr_Occurred()) {
  2118. Py_DECREF(list);
  2119. list = NULL;
  2120. }
  2121. return list;
  2122. }
  2123. LPCIID List_to_LPCIID(PyObject *list, ULONG *cInterfaces)
  2124. {
  2125. PyObject *iter = NULL;
  2126. PyObject *elem = NULL;
  2127. Py_ssize_t len = 0;
  2128. LPIID lpList = NULL;
  2129. int i = 0;
  2130. if(list == Py_None) {
  2131. cInterfaces = 0;
  2132. return NULL;
  2133. }
  2134. iter = PyObject_GetIter(list);
  2135. if(!iter)
  2136. goto exit;
  2137. len = PyObject_Length(list);
  2138. if (MAPIAllocateBuffer(len * sizeof *lpList, (void **)&lpList) != hrSuccess)
  2139. goto exit;
  2140. while((elem = PyIter_Next(iter))) {
  2141. char *ptr = NULL;
  2142. Py_ssize_t strlen = 0;
  2143. if (PyString_AsStringAndSize(elem, &ptr, &strlen) == -1 ||
  2144. PyErr_Occurred())
  2145. goto exit;
  2146. if (strlen != sizeof(*lpList)) {
  2147. PyErr_Format(PyExc_RuntimeError, "IID parameter must be exactly %d bytes", (int)sizeof(IID));
  2148. goto exit;
  2149. }
  2150. memcpy(&lpList[i], ptr, sizeof(*lpList));
  2151. ++i;
  2152. Py_DECREF(elem);
  2153. elem = NULL;
  2154. }
  2155. *cInterfaces = len;
  2156. exit:
  2157. if(PyErr_Occurred()) {
  2158. MAPIFreeBuffer(lpList);
  2159. lpList = NULL;
  2160. }
  2161. if (elem != nullptr)
  2162. Py_DECREF(elem);
  2163. if (iter != nullptr)
  2164. Py_DECREF(iter);
  2165. return lpList;
  2166. }
  2167. PyObject *List_from_LPCIID(LPCIID iids, ULONG cElements)
  2168. {
  2169. if (iids == NULL) {
  2170. Py_INCREF(Py_None);
  2171. return(Py_None);
  2172. }
  2173. PyObject *list = PyList_New(0);
  2174. PyObject *iid = NULL;
  2175. for (unsigned int i = 0; i < cElements; ++i) {
  2176. iid = PyString_FromStringAndSize((char*)&iids[i], sizeof(IID));
  2177. if (PyErr_Occurred())
  2178. goto exit;
  2179. PyList_Append(list, iid);
  2180. Py_DECREF(iid);
  2181. iid = NULL;
  2182. }
  2183. exit:
  2184. if (PyErr_Occurred()) {
  2185. Py_DECREF(list);
  2186. list = NULL;
  2187. }
  2188. return list;
  2189. }
  2190. template<typename T> void
  2191. Object_to_MVPROPMAP(PyObject *elem, T *&lpObj, ULONG ulFlags)
  2192. {
  2193. HRESULT hr = hrSuccess;
  2194. PyObject *MVPropMaps, *Item, *PropID, *ListItem, *Values;
  2195. int ValuesLength, MVPropMapsSize = 0;
  2196. /* Multi-Value PropMap support. */
  2197. MVPropMaps = PyObject_GetAttrString(elem, "MVPropMap");
  2198. if (MVPropMaps == NULL || !PyList_Check(MVPropMaps)) {
  2199. Py_XDECREF(MVPropMaps);
  2200. return;
  2201. }
  2202. MVPropMapsSize = PyList_Size(MVPropMaps);
  2203. /* No PropMaps - bail out */
  2204. if (MVPropMapsSize != 2) {
  2205. PyErr_SetString(PyExc_TypeError, "MVPropMap should contain two entries");
  2206. Py_DECREF(MVPropMaps);
  2207. return;
  2208. }
  2209. /* If we have more mv props than the feature lists, adjust this value! */
  2210. lpObj->sMVPropmap.cEntries = 2;
  2211. hr = MAPIAllocateMore(sizeof(MVPROPMAPENTRY) * lpObj->sMVPropmap.cEntries, lpObj, reinterpret_cast<void **>(&lpObj->sMVPropmap.lpEntries));
  2212. for (int i = 0; i < MVPropMapsSize; ++i) {
  2213. Item = PyList_GetItem(MVPropMaps, i);
  2214. PropID = PyObject_GetAttrString(Item, "ulPropId");
  2215. Values = PyObject_GetAttrString(Item, "Values");
  2216. if (PropID == NULL || Values == NULL || !PyList_Check(Values)) {
  2217. PyErr_SetString(PyExc_TypeError, "ulPropId or Values is empty or values is not a list");
  2218. Py_XDECREF(PropID);
  2219. Py_XDECREF(Values);
  2220. Py_DECREF(MVPropMaps);
  2221. return;
  2222. }
  2223. /* Set default struct entry to empty stub values */
  2224. lpObj->sMVPropmap.lpEntries[i].ulPropId = PyLong_AsUnsignedLong(PropID);
  2225. lpObj->sMVPropmap.lpEntries[i].cValues = 0;
  2226. lpObj->sMVPropmap.lpEntries[i].lpszValues = NULL;
  2227. //if ((PropID != NULL && PropID != Py_None) && (Values != NULL && Values != Py_None && PyList_Check(Values)))
  2228. ValuesLength = PyList_Size(Values);
  2229. lpObj->sMVPropmap.lpEntries[i].cValues = ValuesLength;
  2230. if (ValuesLength > 0) {
  2231. hr = MAPIAllocateMore(sizeof(LPTSTR) * lpObj->sMVPropmap.lpEntries[i].cValues, lpObj, reinterpret_cast<void **>(&lpObj->sMVPropmap.lpEntries[i].lpszValues));
  2232. if (hr != hrSuccess) {
  2233. PyErr_SetString(PyExc_RuntimeError, "Out of memory");
  2234. Py_DECREF(PropID);
  2235. Py_DECREF(Values);
  2236. Py_DECREF(MVPropMaps);
  2237. return;
  2238. }
  2239. }
  2240. for (int j = 0; j < ValuesLength; ++j) {
  2241. ListItem = PyList_GetItem(Values, j);
  2242. if (ListItem != Py_None) {
  2243. if ((ulFlags & MAPI_UNICODE) == 0)
  2244. // XXX: meh, not sure what todo here. Maybe use process_conv_out??
  2245. lpObj->sMVPropmap.lpEntries[i].lpszValues[j] = reinterpret_cast<TCHAR *>(PyString_AsString(ListItem));
  2246. else
  2247. CopyPyUnicode(&lpObj->sMVPropmap.lpEntries[i].lpszValues[j], ListItem, lpObj);
  2248. }
  2249. }
  2250. Py_DECREF(PropID);
  2251. Py_DECREF(Values);
  2252. }
  2253. Py_DECREF(MVPropMaps);
  2254. }
  2255. PyObject *Object_from_MVPROPMAP(MVPROPMAP propmap, ULONG ulFlags)
  2256. {
  2257. /*
  2258. * Multi-Value PropMap support.
  2259. *
  2260. * This holds the enabled/disabled features of a user. It is
  2261. * represented as a list of PropMaps which contains multiple values. A
  2262. * Normal Propmap only contains one value, so we use a list to display
  2263. * these values.
  2264. *
  2265. * Note that the enabled/disabled MVPropMap is special since, for
  2266. * example, setting both PR_EC_ENABLED_FEATUES and
  2267. * PR_EC_DISALBED_FEATURES to an empty list will still set the features
  2268. * to either disabled or enabled according to the default set in the
  2269. * server configuration.
  2270. */
  2271. PyObject *MVProps = PyList_New(0);
  2272. PyObject *MVPropValues, *MVPropMap, *MVPropValue = NULL;
  2273. MVPROPMAP *lpMVPropmap = &propmap;
  2274. for (unsigned int i = 0; i < lpMVPropmap->cEntries; ++i) {
  2275. PyObject *MVPropValues = PyList_New(0);
  2276. for (unsigned int j = 0; j < lpMVPropmap->lpEntries[i].cValues; ++j) {
  2277. LPTSTR strval = lpMVPropmap->lpEntries[i].lpszValues[j];
  2278. std::string str = reinterpret_cast<LPSTR>(strval);
  2279. if (str.empty())
  2280. continue;
  2281. if (ulFlags & MAPI_UNICODE)
  2282. MVPropValue = PyUnicode_FromWideChar(strval, wcslen(strval));
  2283. else
  2284. MVPropValue = PyString_FromStringAndSize(str.c_str(), str.length());
  2285. PyList_Append(MVPropValues, MVPropValue);
  2286. Py_DECREF(MVPropValue);
  2287. MVPropValue = NULL;
  2288. }
  2289. MVPropMap = PyObject_CallFunction(PyTypeMVPROPMAP, "(lO)", lpMVPropmap->lpEntries[i].ulPropId, MVPropValues);
  2290. Py_DECREF(MVPropValues);
  2291. PyList_Append(MVProps, MVPropMap);
  2292. Py_DECREF(MVPropMap);
  2293. MVPropMap = NULL;
  2294. MVPropValues = NULL;
  2295. }
  2296. return MVProps;
  2297. }
  2298. ECUSER *Object_to_LPECUSER(PyObject *elem, ULONG ulFlags)
  2299. {
  2300. static conv_out_info<ECUSER> conv_info[] = {
  2301. {conv_out_default<ECUSER, LPTSTR, &ECUSER::lpszUsername>, "Username"},
  2302. {conv_out_default<ECUSER, LPTSTR, &ECUSER::lpszPassword>, "Password"},
  2303. {conv_out_default<ECUSER, LPTSTR, &ECUSER::lpszMailAddress>, "Email"},
  2304. {conv_out_default<ECUSER, LPTSTR, &ECUSER::lpszFullName>, "FullName"},
  2305. {conv_out_default<ECUSER, LPTSTR, &ECUSER::lpszServername>, "Servername"},
  2306. {conv_out_default<ECUSER, objectclass_t, &ECUSER::ulObjClass>, "Class"},
  2307. {conv_out_default<ECUSER, unsigned int, &ECUSER::ulIsAdmin>, "IsAdmin"},
  2308. {conv_out_default<ECUSER, unsigned int, &ECUSER::ulIsABHidden>, "IsHidden"},
  2309. {conv_out_default<ECUSER, unsigned int, &ECUSER::ulCapacity>, "Capacity"},
  2310. {conv_out_default<ECUSER, ECENTRYID, &ECUSER::sUserId>, "UserID"},
  2311. };
  2312. HRESULT hr = hrSuccess;
  2313. ECUSER *lpUser = NULL;
  2314. if (elem == Py_None)
  2315. goto exit;
  2316. hr = MAPIAllocateBuffer(sizeof *lpUser, (LPVOID*)&lpUser);
  2317. if (hr != hrSuccess) {
  2318. PyErr_SetString(PyExc_RuntimeError, "Out of memory");
  2319. goto exit;
  2320. }
  2321. memset(lpUser, 0, sizeof *lpUser);
  2322. process_conv_out_array(lpUser, elem, conv_info, lpUser, ulFlags);
  2323. Object_to_MVPROPMAP(elem, lpUser, ulFlags);
  2324. exit:
  2325. if (PyErr_Occurred()) {
  2326. MAPIFreeBuffer(lpUser);
  2327. lpUser = NULL;
  2328. }
  2329. return lpUser;
  2330. }
  2331. PyObject *Object_from_LPECUSER(ECUSER *lpUser, ULONG ulFlags)
  2332. {
  2333. PyObject *MVProps = Object_from_MVPROPMAP(lpUser->sMVPropmap, ulFlags);
  2334. PyObject *userid = PyBytes_FromStringAndSize((const char *)lpUser->sUserId.lpb, lpUser->sUserId.cb);
  2335. PyObject *result = NULL;
  2336. if (ulFlags & MAPI_UNICODE)
  2337. result = PyObject_CallFunction(PyTypeECUser, "(uuuuullllOO)", lpUser->lpszUsername, lpUser->lpszPassword, lpUser->lpszMailAddress, lpUser->lpszFullName, lpUser->lpszServername, lpUser->ulObjClass, lpUser->ulIsAdmin, lpUser->ulIsABHidden, lpUser->ulCapacity, userid, MVProps);
  2338. else
  2339. result = PyObject_CallFunction(PyTypeECUser, "(sssssllllOO)", lpUser->lpszUsername, lpUser->lpszPassword, lpUser->lpszMailAddress, lpUser->lpszFullName, lpUser->lpszServername, lpUser->ulObjClass, lpUser->ulIsAdmin, lpUser->ulIsABHidden, lpUser->ulCapacity, userid, MVProps);
  2340. Py_DECREF(MVProps);
  2341. Py_DECREF(userid);
  2342. return result;
  2343. }
  2344. PyObject *List_from_LPECUSER(ECUSER *lpUser, ULONG cElements, ULONG ulFlags)
  2345. {
  2346. PyObject *list = PyList_New(0);
  2347. PyObject *item = NULL;
  2348. for (unsigned int i = 0; i < cElements; ++i) {
  2349. item = Object_from_LPECUSER(&lpUser[i], ulFlags);
  2350. if (PyErr_Occurred())
  2351. goto exit;
  2352. PyList_Append(list, item);
  2353. Py_DECREF(item);
  2354. item = NULL;
  2355. }
  2356. exit:
  2357. if(PyErr_Occurred()) {
  2358. if (list != nullptr)
  2359. Py_DECREF(list);
  2360. list = NULL;
  2361. }
  2362. if (item != nullptr)
  2363. Py_DECREF(item);
  2364. return list;
  2365. }
  2366. ECGROUP *Object_to_LPECGROUP(PyObject *elem, ULONG ulFlags)
  2367. {
  2368. static conv_out_info<ECGROUP> conv_info[] = {
  2369. {conv_out_default<ECGROUP, LPTSTR, &ECGROUP::lpszGroupname>, "Groupname"},
  2370. {conv_out_default<ECGROUP, LPTSTR, &ECGROUP::lpszFullname>, "Fullname"},
  2371. {conv_out_default<ECGROUP, LPTSTR, &ECGROUP::lpszFullEmail>, "Email"},
  2372. {conv_out_default<ECGROUP, unsigned int, &ECGROUP::ulIsABHidden>, "IsHidden"},
  2373. {conv_out_default<ECGROUP, ECENTRYID, &ECGROUP::sGroupId>, "GroupID"},
  2374. };
  2375. HRESULT hr = hrSuccess;
  2376. ECGROUP *lpGroup = NULL;
  2377. if (elem == Py_None)
  2378. goto exit;
  2379. hr = MAPIAllocateBuffer(sizeof *lpGroup, (LPVOID*)&lpGroup);
  2380. if (hr != hrSuccess) {
  2381. PyErr_SetString(PyExc_RuntimeError, "Out of memory");
  2382. goto exit;
  2383. }
  2384. memset(lpGroup, 0, sizeof *lpGroup);
  2385. process_conv_out_array(lpGroup, elem, conv_info, lpGroup, ulFlags);
  2386. Object_to_MVPROPMAP(elem, lpGroup, ulFlags);
  2387. exit:
  2388. if (PyErr_Occurred()) {
  2389. MAPIFreeBuffer(lpGroup);
  2390. lpGroup = NULL;
  2391. }
  2392. return lpGroup;
  2393. }
  2394. PyObject *Object_from_LPECGROUP(ECGROUP *lpGroup, ULONG ulFlags)
  2395. {
  2396. PyObject *MVProps = Object_from_MVPROPMAP(lpGroup->sMVPropmap, ulFlags);
  2397. PyObject *groupid = PyBytes_FromStringAndSize((const char *)lpGroup->sGroupId.lpb, lpGroup->sGroupId.cb);
  2398. PyObject *result = NULL;
  2399. if(ulFlags & MAPI_UNICODE)
  2400. result = PyObject_CallFunction(PyTypeECGroup, "(uuulOO)", lpGroup->lpszGroupname, lpGroup->lpszFullname, lpGroup->lpszFullEmail, lpGroup->ulIsABHidden, groupid, MVProps);
  2401. else
  2402. result = PyObject_CallFunction(PyTypeECGroup, "(ssslOO)", lpGroup->lpszGroupname, lpGroup->lpszFullname, lpGroup->lpszFullEmail, lpGroup->ulIsABHidden, groupid, MVProps);
  2403. Py_DECREF(MVProps);
  2404. Py_DECREF(groupid);
  2405. return result;
  2406. }
  2407. PyObject *List_from_LPECGROUP(ECGROUP *lpGroup, ULONG cElements, ULONG ulFlags)
  2408. {
  2409. PyObject *list = PyList_New(0);
  2410. PyObject *item = NULL;
  2411. for (unsigned int i = 0; i < cElements; ++i) {
  2412. item = Object_from_LPECGROUP(&lpGroup[i], ulFlags);
  2413. if (PyErr_Occurred())
  2414. goto exit;
  2415. PyList_Append(list, item);
  2416. Py_DECREF(item);
  2417. item = NULL;
  2418. }
  2419. exit:
  2420. if(PyErr_Occurred()) {
  2421. if (list != nullptr)
  2422. Py_DECREF(list);
  2423. list = NULL;
  2424. }
  2425. if (item != nullptr)
  2426. Py_DECREF(item);
  2427. return list;
  2428. }
  2429. ECCOMPANY *Object_to_LPECCOMPANY(PyObject *elem, ULONG ulFlags)
  2430. {
  2431. static conv_out_info<ECCOMPANY> conv_info[] = {
  2432. {conv_out_default<ECCOMPANY, LPTSTR, &ECCOMPANY::lpszCompanyname>, "Companyname"},
  2433. {conv_out_default<ECCOMPANY, LPTSTR, &ECCOMPANY::lpszServername>, "Servername"},
  2434. {conv_out_default<ECCOMPANY, unsigned int, &ECCOMPANY::ulIsABHidden>, "IsHidden"},
  2435. {conv_out_default<ECCOMPANY, ECENTRYID, &ECCOMPANY::sCompanyId>, "CompanyID"},
  2436. {conv_out_default<ECCOMPANY, ECENTRYID, &ECCOMPANY::sAdministrator>, "AdministratorID"},
  2437. };
  2438. HRESULT hr = hrSuccess;
  2439. ECCOMPANY *lpCompany = NULL;
  2440. if (elem == Py_None)
  2441. goto exit;
  2442. hr = MAPIAllocateBuffer(sizeof *lpCompany, (LPVOID*)&lpCompany);
  2443. if (hr != hrSuccess) {
  2444. PyErr_SetString(PyExc_RuntimeError, "Out of memory");
  2445. goto exit;
  2446. }
  2447. memset(lpCompany, 0, sizeof *lpCompany);
  2448. process_conv_out_array(lpCompany, elem, conv_info, lpCompany, ulFlags);
  2449. Object_to_MVPROPMAP(elem, lpCompany, ulFlags);
  2450. exit:
  2451. if (PyErr_Occurred()) {
  2452. MAPIFreeBuffer(lpCompany);
  2453. lpCompany = NULL;
  2454. }
  2455. return lpCompany;
  2456. }
  2457. PyObject *Object_from_LPECCOMPANY(ECCOMPANY *lpCompany, ULONG ulFlags)
  2458. {
  2459. PyObject *MVProps = Object_from_MVPROPMAP(lpCompany->sMVPropmap, ulFlags);
  2460. PyObject *companyid = PyBytes_FromStringAndSize((const char *)lpCompany->sCompanyId.lpb, lpCompany->sCompanyId.cb);
  2461. PyObject *adminid = PyBytes_FromStringAndSize((const char *)lpCompany->sAdministrator.lpb, lpCompany->sAdministrator.cb);
  2462. PyObject *result = NULL;
  2463. if(ulFlags & MAPI_UNICODE)
  2464. result = PyObject_CallFunction(PyTypeECCompany, "(uulOO)", lpCompany->lpszCompanyname, lpCompany->lpszServername, lpCompany->ulIsABHidden, companyid, MVProps, adminid);
  2465. else
  2466. result = PyObject_CallFunction(PyTypeECCompany, "(sslOO)", lpCompany->lpszCompanyname, lpCompany->lpszServername, lpCompany->ulIsABHidden, companyid, MVProps, adminid);
  2467. Py_DECREF(MVProps);
  2468. Py_DECREF(companyid);
  2469. Py_DECREF(adminid);
  2470. return result;
  2471. }
  2472. PyObject *List_from_LPECCOMPANY(ECCOMPANY *lpCompany, ULONG cElements,
  2473. ULONG ulFlags)
  2474. {
  2475. PyObject *list = PyList_New(0);
  2476. PyObject *item = NULL;
  2477. for (unsigned int i = 0; i < cElements; ++i) {
  2478. item = Object_from_LPECCOMPANY(&lpCompany[i], ulFlags);
  2479. if (PyErr_Occurred())
  2480. goto exit;
  2481. PyList_Append(list, item);
  2482. Py_DECREF(item);
  2483. item = NULL;
  2484. }
  2485. exit:
  2486. if(PyErr_Occurred()) {
  2487. if (list != nullptr)
  2488. Py_DECREF(list);
  2489. list = NULL;
  2490. }
  2491. if (item != nullptr)
  2492. Py_DECREF(item);
  2493. return list;
  2494. }
  2495. PyObject *Object_from_LPECUSERCLIENTUPDATESTATUS(ECUSERCLIENTUPDATESTATUS *lpECUCUS)
  2496. {
  2497. // @todo charset conversion ?
  2498. return PyObject_CallFunction(PyTypeECUserClientUpdateStatus, "(llsssl)", lpECUCUS->ulTrackId, lpECUCUS->tUpdatetime, lpECUCUS->lpszCurrentversion, lpECUCUS->lpszLatestversion, lpECUCUS->lpszComputername, lpECUCUS->ulStatus);
  2499. }
  2500. LPROWLIST List_to_LPROWLIST(PyObject *object, ULONG ulFlags)
  2501. {
  2502. PyObject *elem = NULL;
  2503. PyObject *iter = NULL;
  2504. PyObject *rowflags = NULL;
  2505. PyObject *props = NULL;
  2506. Py_ssize_t len = 0;
  2507. LPROWLIST lpRowList = NULL;
  2508. int n = 0;
  2509. if (object == Py_None)
  2510. return NULL;
  2511. len = PyObject_Length(object);
  2512. if (len < 0) {
  2513. PyErr_Format(PyExc_TypeError, "Invalid list passed as row list");
  2514. goto exit;
  2515. }
  2516. if (MAPIAllocateBuffer(CbNewROWLIST(len), (void **)&lpRowList) != hrSuccess)
  2517. goto exit;
  2518. iter = PyObject_GetIter(object);
  2519. if (iter == NULL)
  2520. goto exit;
  2521. while ((elem = PyIter_Next(iter))) {
  2522. rowflags = PyObject_GetAttrString(elem, "ulRowFlags");
  2523. if (rowflags == NULL)
  2524. goto exit;
  2525. props = PyObject_GetAttrString(elem, "rgPropVals");
  2526. if (props == NULL)
  2527. goto exit;
  2528. lpRowList->aEntries[n].ulRowFlags = (ULONG)PyLong_AsUnsignedLong(rowflags);
  2529. lpRowList->aEntries[n].rgPropVals = List_to_LPSPropValue(props, &lpRowList->aEntries[n].cValues, ulFlags);
  2530. Py_DECREF(props);
  2531. props = NULL;
  2532. Py_DECREF(rowflags);
  2533. rowflags = NULL;
  2534. Py_DECREF(elem);
  2535. elem = NULL;
  2536. ++n;
  2537. }
  2538. lpRowList->cEntries = n;
  2539. exit:
  2540. if (PyErr_Occurred()) {
  2541. MAPIFreeBuffer(lpRowList);
  2542. lpRowList = NULL;
  2543. }
  2544. if (props)
  2545. Py_DECREF(props);
  2546. if (rowflags)
  2547. Py_DECREF(rowflags);
  2548. if (elem)
  2549. Py_DECREF(elem);
  2550. if (iter)
  2551. Py_DECREF(iter);
  2552. return lpRowList;
  2553. }
  2554. void DoException(HRESULT hr)
  2555. {
  2556. #if PY_VERSION_HEX >= 0x02040300 // 2.4.3
  2557. PyObject *hrObj = Py_BuildValue("I", (unsigned int)hr);
  2558. #else
  2559. // Python 2.4.2 and earlier don't support the "I" format so create a
  2560. // PyLong object instead.
  2561. PyObject *hrObj = PyLong_FromUnsignedLong((unsigned int)hr);
  2562. #endif
  2563. #if PY_MAJOR_VERSION >= 3
  2564. PyObject *attr_name = PyUnicode_FromString("_errormap");
  2565. #else
  2566. PyObject *attr_name = PyString_FromString("_errormap");
  2567. #endif
  2568. PyObject *errormap = PyObject_GetAttr(PyTypeMAPIError, attr_name);
  2569. PyObject *errortype = NULL;
  2570. PyObject *ex = NULL;
  2571. if (errormap != NULL) {
  2572. errortype = PyDict_GetItem(errormap, hrObj);
  2573. if (errortype)
  2574. ex = PyObject_CallFunction(errortype, NULL);
  2575. }
  2576. if (!errortype) {
  2577. errortype = PyTypeMAPIError;
  2578. ex = PyObject_CallFunction(PyTypeMAPIError, "O", hrObj);
  2579. }
  2580. PyErr_SetObject(errortype, ex);
  2581. if (ex)
  2582. Py_DECREF(ex);
  2583. if (errormap)
  2584. Py_DECREF(errormap);
  2585. if (attr_name)
  2586. Py_DECREF(attr_name);
  2587. if (hrObj)
  2588. Py_DECREF(hrObj);
  2589. }
  2590. int GetExceptionError(PyObject *object, HRESULT *lphr)
  2591. {
  2592. if (!PyErr_GivenExceptionMatches(object, PyTypeMAPIError))
  2593. return 0;
  2594. PyObject *type = NULL, *value = NULL, *traceback = NULL;
  2595. PyErr_Fetch(&type, &value, &traceback);
  2596. PyObject *hr = PyObject_GetAttrString(value, "hr");
  2597. if (!hr) {
  2598. PyErr_SetString(PyExc_RuntimeError, "hr or Value missing from MAPIError");
  2599. return -1;
  2600. }
  2601. *lphr = (HRESULT)PyLong_AsUnsignedLong(hr);
  2602. Py_DECREF(hr);
  2603. if (type != nullptr)
  2604. Py_DECREF(type);
  2605. if (value != nullptr)
  2606. Py_DECREF(value);
  2607. if (traceback != nullptr)
  2608. Py_DECREF(traceback);
  2609. return 1;
  2610. }
  2611. ECQUOTA *Object_to_LPECQUOTA(PyObject *elem)
  2612. {
  2613. static conv_out_info<ECQUOTA> conv_info[] = {
  2614. {conv_out_default<ECQUOTA, bool, &ECQUOTA::bUseDefaultQuota>, "bUseDefaultQuota"},
  2615. {conv_out_default<ECQUOTA, bool, &ECQUOTA::bIsUserDefaultQuota>, "bIsUserDefaultQuota"},
  2616. {conv_out_default<ECQUOTA, int64_t, &ECQUOTA::llWarnSize>, "llWarnSize"},
  2617. {conv_out_default<ECQUOTA, int64_t, &ECQUOTA::llSoftSize>, "llSoftSize"},
  2618. {conv_out_default<ECQUOTA, int64_t, &ECQUOTA::llHardSize>, "llHardSize"},
  2619. };
  2620. HRESULT hr = hrSuccess;
  2621. ECQUOTA *lpQuota = NULL;
  2622. if (elem == Py_None)
  2623. goto exit;
  2624. hr = MAPIAllocateBuffer(sizeof *lpQuota, (LPVOID*)&lpQuota);
  2625. if (hr != hrSuccess) {
  2626. PyErr_SetString(PyExc_RuntimeError, "Out of memory");
  2627. goto exit;
  2628. }
  2629. memset(lpQuota, 0, sizeof *lpQuota);
  2630. process_conv_out_array(lpQuota, elem, conv_info, lpQuota, 0);
  2631. exit:
  2632. if (PyErr_Occurred()) {
  2633. MAPIFreeBuffer(lpQuota);
  2634. lpQuota = NULL;
  2635. }
  2636. return lpQuota;
  2637. }
  2638. PyObject *Object_from_LPECQUOTA(ECQUOTA *lpQuota)
  2639. {
  2640. return PyObject_CallFunction(PyTypeECQuota, "(llLLL)", lpQuota->bUseDefaultQuota, lpQuota->bIsUserDefaultQuota, lpQuota->llWarnSize, lpQuota->llSoftSize, lpQuota->llHardSize);
  2641. }
  2642. PyObject *Object_from_LPECQUOTASTATUS(ECQUOTASTATUS *lpQuotaStatus)
  2643. {
  2644. return PyObject_CallFunction(PyTypeECQuotaStatus, "Ll", lpQuotaStatus->llStoreSize, lpQuotaStatus->quotaStatus);
  2645. }
  2646. ECSVRNAMELIST *List_to_LPECSVRNAMELIST(PyObject *object)
  2647. {
  2648. HRESULT hr = hrSuccess;
  2649. Py_ssize_t len = 0;
  2650. PyObject *iter = NULL;
  2651. PyObject *elem = NULL;
  2652. ECSVRNAMELIST *lpSvrNameList = NULL;
  2653. if (object == Py_None)
  2654. goto exit;
  2655. len = PyObject_Length(object);
  2656. if (len < 0) {
  2657. PyErr_Format(PyExc_TypeError, "Invalid list passed as servername list");
  2658. goto exit;
  2659. }
  2660. if (MAPIAllocateBuffer(sizeof(ECSVRNAMELIST) + (sizeof(ECSERVER *) * len), reinterpret_cast<void **>(&lpSvrNameList)) != hrSuccess)
  2661. goto exit;
  2662. memset(lpSvrNameList, 0, sizeof(ECSVRNAMELIST) + (sizeof(ECSERVER *) * len) );
  2663. iter = PyObject_GetIter(object);
  2664. if (iter == NULL)
  2665. goto exit;
  2666. while ((elem = PyIter_Next(iter))) {
  2667. char *ptr = NULL;
  2668. Py_ssize_t strlen = 0;
  2669. if (PyString_AsStringAndSize(elem, &ptr, &strlen) == -1 ||
  2670. PyErr_Occurred())
  2671. goto exit;
  2672. hr = MAPIAllocateMore(strlen, lpSvrNameList, (void**)&lpSvrNameList->lpszaServer[lpSvrNameList->cServers]);
  2673. if (hr != hrSuccess) {
  2674. PyErr_SetString(PyExc_RuntimeError, "Out of memory");
  2675. goto exit;
  2676. }
  2677. memcpy(lpSvrNameList->lpszaServer[lpSvrNameList->cServers], ptr, strlen);
  2678. Py_DECREF(elem);
  2679. elem = NULL;
  2680. ++lpSvrNameList->cServers;
  2681. }
  2682. exit:
  2683. if(PyErr_Occurred()) {
  2684. MAPIFreeBuffer(lpSvrNameList);
  2685. lpSvrNameList = NULL;
  2686. }
  2687. if (elem != nullptr)
  2688. Py_DECREF(elem);
  2689. if (iter != nullptr)
  2690. Py_DECREF(iter);
  2691. return lpSvrNameList;
  2692. }
  2693. PyObject *Object_from_LPECSERVER(ECSERVER *lpServer)
  2694. {
  2695. return PyObject_CallFunction(PyTypeECServer, "(sssssl)", lpServer->lpszName, lpServer->lpszFilePath, lpServer->lpszHttpPath, lpServer->lpszSslPath, lpServer->lpszPreferedPath, lpServer->ulFlags);
  2696. }
  2697. PyObject *List_from_LPECSERVERLIST(ECSERVERLIST *lpServerList)
  2698. {
  2699. PyObject *list = PyList_New(0);
  2700. PyObject *item = NULL;
  2701. for (unsigned int i = 0; i < lpServerList->cServers; ++i) {
  2702. item = Object_from_LPECSERVER(&lpServerList->lpsaServer[i]);
  2703. if (PyErr_Occurred())
  2704. goto exit;
  2705. PyList_Append(list, item);
  2706. Py_DECREF(item);
  2707. item = NULL;
  2708. }
  2709. exit:
  2710. if(PyErr_Occurred()) {
  2711. if (list != nullptr)
  2712. Py_DECREF(list);
  2713. list = NULL;
  2714. }
  2715. if (item != nullptr)
  2716. Py_DECREF(item);
  2717. return list;
  2718. }
  2719. void Object_to_STATSTG(PyObject *object, STATSTG *stg)
  2720. {
  2721. PyObject *cbSize = NULL;
  2722. if(object == Py_None) {
  2723. PyErr_Format(PyExc_TypeError, "Invalid None passed for STATSTG");
  2724. goto exit;
  2725. }
  2726. cbSize = PyObject_GetAttrString(object, "cbSize");
  2727. if(!cbSize) {
  2728. PyErr_Format(PyExc_TypeError, "STATSTG does not contain cbSize");
  2729. goto exit;
  2730. }
  2731. stg->cbSize.QuadPart = PyLong_AsINT64(cbSize);
  2732. exit:
  2733. if (cbSize != nullptr)
  2734. Py_DECREF(cbSize);
  2735. }
  2736. PyObject *Object_from_STATSTG(STATSTG *lpStatStg)
  2737. {
  2738. PyObject *result = NULL;
  2739. PyObject *cbSize = NULL;
  2740. if(lpStatStg == NULL) {
  2741. Py_INCREF(Py_None);
  2742. return Py_None;
  2743. }
  2744. cbSize = PyLong_FromLongLong(lpStatStg->cbSize.QuadPart);
  2745. result = PyObject_CallFunction(PyTypeSTATSTG, "(O)", cbSize);
  2746. if (cbSize != nullptr)
  2747. Py_DECREF(cbSize);
  2748. if(PyErr_Occurred()) {
  2749. if (result != nullptr)
  2750. Py_DECREF(result);
  2751. result = NULL;
  2752. }
  2753. return result;
  2754. }
  2755. PyObject *Object_from_SYSTEMTIME(const SYSTEMTIME &time)
  2756. {
  2757. return PyObject_CallFunction(PyTypeSYSTEMTIME, "(iiiiiiii)",
  2758. time.wYear, time.wMonth, time.wDayOfWeek, time.wDay,
  2759. time.wHour, time.wMinute, time.wSecond, time.wMilliseconds);
  2760. }
  2761. SYSTEMTIME Object_to_SYSTEMTIME(PyObject *object)
  2762. {
  2763. static conv_out_info<SYSTEMTIME> conv_info[] = {
  2764. {conv_out_default<SYSTEMTIME, WORD, &SYSTEMTIME::wYear>, "wYear"},
  2765. {conv_out_default<SYSTEMTIME, WORD, &SYSTEMTIME::wMonth>, "wMonth"},
  2766. {conv_out_default<SYSTEMTIME, WORD, &SYSTEMTIME::wDayOfWeek>, "wDayOfWeek"},
  2767. {conv_out_default<SYSTEMTIME, WORD, &SYSTEMTIME::wDay>, "wDay"},
  2768. {conv_out_default<SYSTEMTIME, WORD, &SYSTEMTIME::wHour>, "wHour"},
  2769. {conv_out_default<SYSTEMTIME, WORD, &SYSTEMTIME::wMinute>, "wMinute"},
  2770. {conv_out_default<SYSTEMTIME, WORD, &SYSTEMTIME::wSecond>, "wSecond"},
  2771. {conv_out_default<SYSTEMTIME, WORD, &SYSTEMTIME::wMilliseconds>, "wMilliseconds"},
  2772. };
  2773. HRESULT hr = hrSuccess;
  2774. SYSTEMTIME st = {0};
  2775. if (object == Py_None)
  2776. return st;
  2777. process_conv_out_array(&st, object, conv_info, NULL, 0);
  2778. return st;
  2779. }