[rt.cpan.org #55660] [PATCH] Partial win64 support for Win32::API

[email protected] ("Stephen Bennett via RT")
Newsgroups perl.libwin32
Message-ID <[email protected]>
Wed Mar 17 10:09:53 2010: Request 55660 was acted upon.
Transaction: Ticket created by [email protected]
       Queue: Win32-API
     Subject: [PATCH] Partial win64 support for Win32::API
   Broken in: (no value)
    Severity: (no value)
       Owner: Nobody
  Requestors: [email protected]
      Status: new
 Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=55660 >


The attached three patches (against Win32-API-0.59) implement initial support for 64-bit Windows in Win32-API.

I didn't attempt to port Win32::API::Callback. It looks like considerably more effort than Win32::API itself, and as our application doesn't need it I couldn't justify the paid time to spend on it. This is, however, sufficient for Win32::API tests to pass against a 64-bit ActivePerl 5.8.9.

At present, only MSVC++ toolchains will work, as its assembly dialect is different from GNU. I don't have a gcc-based build of Perl to work with to port it, but it should only require a straightforward translation of call_asm_x64_msvc.asm into call_asm_x64_gnu.asm.

The required changes to Makefile.PL are also somewhat hackish, purely because I don't know of a better way to detect what architecture we're targeting.

Accelrys Limited (http://accelrys.com)
Registered office: 334 Cambridge Science Park, Cambridge, CB4 0WN, UK
Registered in England: 2326316
0003-Add-an-x64-platform-to-the-API_test-project-and-an-x.patch (application/octet-stream, 60.5 KB)
From c48b76837523515394075db5288081b9c789aab5 Mon Sep 17 00:00:00 2001
From: Stephen Bennett <[email protected]>
Date: Tue, 16 Mar 2010 18:08:13 +0000
Subject: [PATCH 3/3] Add an x64 platform to the API_test project, and an x64 build of the
 DLL. Use it in tests where appropriate.

---
 API_test64.dll           |  Bin 0 -> 71680 bytes
 Test.pm                  |    6 +
 api-test/API_test.sln    |    8 ++-
 api-test/API_test.suo    |  Bin 7680 -> 8192 bytes
 api-test/API_test.vcproj |  232 +++++++++++++++++++++++++++++++++++++++++++++-
 t/00_API.t               |    3 +-
 t/01_Struct.t            |    3 +-
 7 files changed, 248 insertions(+), 4 deletions(-)
 create mode 100755 API_test64.dll

diff --git a/API_test64.dll b/API_test64.dll
new file mode 100755
index 0000000000000000000000000000000000000000..e8cb055c8bd7e136c755d2918b41c0a6335a609c
GIT binary patch
literal 71680
zcmeEvdwf*Ywf{_JhD=_ZK^TZUWQ0MZ5sXG9VW7?-6Fnmng^GxZiVa2-R2t3z)&PlT
z(q`C<(p%eF>#g*9+gk0twY?StDr6GKgYXET5}?+gw(en60%#JR=l5Ov%uE8}y}iG`
zet-P(fjRr^=h|!Sz1G@muf0#%z3WUClgVVoe_c13>hYvMulW7%e>#yoc<iRZrZ+Qo
zUS4kw?7V#T!bg|7mQ+6ZNaaJ1yUHJW;)y3!*Y_TFRR*7MJ^F;pcgLNs$DdsA@T8oa
zOn0K{%l_?(&+lzgwj}@ie%!vL2=Bfhf4JpNJXhKZx7;Jr{aYjvzhlc&;(2h(ed2jQ
zJiq&B`9i8A3GvKQlWD;Z2bsn-y*wis*KHc-%1X;HnHmxET_g6ZTs$2jTy3TYh0{zX
z8~xxf`7}`~khHYIoJcVWCCVb_h3|=&bhAlC(JJ6Jk1CvRHoZv=%`}^~+9@LOx5R83
zCICoA{FBcvlc~r6^`ZqPsSmGEk<t~#4}nO1Ct?rya{;PJl?xtHA2OL#0<sJLug3po
z{2%b=#ju!UWHZg3j06V&Cj4~|$b_KRWNMhS#K<W6h`yRKkzmJjz@L}ut6W-HjyQo6
z;6@<#l8fbgc=40S_yYA6xDtK10AZ+aI#U1t-~R#w^@QrC9jU*Fb%-1`^~WBU=0*o3
z@1S>)dR&%<px}uM(&=5KpD@y;4dzgTI(SN>nzKeWD|$545IkPk(3EUJ3D0xe?^d+W
zUDD=L3Ok^%JxV0!ioGV2kG1fRLG5afNu5w3jSY!jAu+bcWK!5Zz72`qB9H1+^d@8q
zep=X|uzBtRMce9nut{O~mwHR}Pqe3m7rPxwSas)$mK7F5wb!Ffg&pTlpxVMi3Ogr_
z^#KZLLpl=AqD?gUU8Lzvir%7~&RzB?;<q6_z?v2IKEDZRY&hb6gE*dtH-vwT@Nvm;
zyS+k@R&D2(P%N9{K*}P@m6m+3-K%CJ@^*^+0wh8BI|v&+V2j;F3RB%)(X-f2q@Uj(
z>V+50*#0KU98e;&-7Zwog4Y(G+hqgl6a)$gg~z2KK6f5JaZcBf<t0&KAO94u%%ZTT
z9jK?oeq6f8_7swSfh>>Wi9#jz{Kh?ftRrmUGYkk7k>Hq-=-iDI%kHGkU4|4sq5u6{
z2i~1{ufEx&PLwuF{0xMSw0Q*bZbzDrHSiw5Mkya71sJZoRY&IFJ~2=T4>Qqw?}G!!
zA|b(hCygD2McH<}1GRmM+E@qc<iA687y=jz_YEwA@!h0EY}?Y&NF?WPL-7dPq_gy9
zTThYUoReonWSSBA6C*O4-om!8DJ^0fDI#r0jW?4~%Q53^xRDk&-ewLG<^FEGHG&eT
z<s-ZSsMu0n*U<-sZB@dGT?x;01j63jKv;3zNhB@8fUa$me%esm5S+j(t^hGj!_h58
zTi|w?N(<Xc3mXde7Pj%HCzwoHs~&$$iB!4ga=Vj&oLR6D2siO3P-GqdY8b^S1zZ{d
zymazU@g88iQG>!}1Gkhk`cfqI@ivilW&vyG8<2S&uTMl6_5Bw0u@)e<=s{psVLA7h
z%_dZ%wV9RToae#2rRN)(l5{!HEa#e(+PzZkGX%_!3kd-w4u!32pq_+>Dy)ul4kbLp
zj=FY2Tq>SD>Tp)wir8A4Z;;s(wDX6qqbwMowtO3M6qnf5Q3@+@usV?~XAEV_;L{<!
zP(5lYarB59(t=J+<VkBT$u-CAC!{CSPDrcG#2%7kgE)bM5WYkyKdD3l?wNcVC{v@G
zfWW2Y0p@ehl(qV7yqQ<!1|oRfgo$fnySd*(XhcMOu%A_XkwbdRx<czpt8Gvnh#|=*
zZLk)_IPzClxfhx+&yjz=ww?e#%UWWG@uaAk$rf&6y)=PmM$g&3(uQ69t|>r7gF4n*
z_ollVnZ0%IxNGoi4!H@ZCIL&_#Y^1?qdklg65f=p8c$@S+-L(G0}~)1O@YW-cQu|&
zw#xM;bSCTrkBNlb>kvtt0+SG!1fvLpm9SaE476NdOrS`i>wzAv&n#^)3aB~KhPCb=
zqe!&No)t~?Gk|{nTJ%$4Z@TNKN^R>BF^7TeJZ;)G(jbCTM1EQ8yL7oli*~VSJiTx)
zf0VeBwlyy?j{K}sJ7o^8X50BkegYwwUf2*Dj>7!V^~O8D<TjHj9^-c)U3cEtM&R3?
zC@`CN_*N0lL|gnSFXetJoxgf5a<}u~E%d%(EMHtA0>d$zN~eh$vvk{T$!v<f4zT&*
z>Bzplc5kql*)}2;NO<-KK!V;Hw*4OO#m?oZK4{}JZ$@Lahk`5kf1(JN(F|V!km8SM
zr_zFR_%(>w)Cz<flPL<?Dy&l>q+X5cSWeuE@y$AP=VL&e!rDRk;XsHB<#gxm6sOIw
z>tRcLIPU~CVqXDM+9?YV(#D^|EHU_{7}^P0hrz9ctK7NrY#_bB&$`*c06Q%5p+i!!
zlMe>ygwUPnD)6k@2-boC%h}a#GL_Y~sp+!52ZO-{V1_{4v3-8FgFl3pjYui<6O>FP
zyxNP7^ih&_+8n$Q)VdC7g?p*cTBN03#-fG*8?#Wfa!AceCdm4}+CzZiv?Vw>RqOGy
zy58G4s%`vkb}}4ryVTL(1`|;f$WtB3Y<h>$GHZ#a5pSCZsR_}kD6C3IkOFyLQ$JpW
z`1i9uc2Hr*XoT6s_zJKVwohTZ65?0I)Br*sjJ*zclQIX@Le2sXKIF8nOPjO!_XEIQ
z-@~c|eMH)TcMM4M{TQX)CDK*|t%}x^Mzh_uhB#jyMzF%nYwUGdD73~>H*`(M8ViEZ
zl8zN&N*dgvAi*sFg%><m@YeqJe|$>UeQUrD0ZeJ=5aFf9sMxV4%{Qe}rMi&;X~FJ9
z?dr|(tf>#HIa5p34AC+gJPM^s(c7y%1!`Za3i}#!ktGO_+SjBZqoOy~SxAM$94|`n
zvJ0Tw0Ugm{u8^*^y?{wrImpoTpz;}TV*oZN>|hy-Vw7WO3C`l;^JdThn&)-}!lUAs
z5MsSN0Hpbdg1+!5biIHCIiz0fO-z)+y|Exs1J5t$DP-te$k2rt>`QW$@CuhaTfR#s
z3eOC%j}`X3dp!oJ!ocB`)>3xTU*5^*oYeKw!Y}-uv%z9+8*4Jjk^6`D3)V1X@nTST
z)MWsqXt7%%asaXfQ)5lBcR|21&)=8d$Xk%-ZIaI4EdJLq$>KYS^xgzD<6C65P4;{!
z-O;2qWGF8LJYCBrzMAS8hk9Zvx~Z@~2$t+C`h)ugM5;GwD@_yq>}#*|e6wQdtvw`5
zFK;WY{X!jy@yb`-VKVv4(aHybh}W!GcJa}`A$mxq6t+K@-kd&BiQH{Qv#Um}nQpEV
zgRuZ)J#RE-CfoC~oq>pLe+#78^HIfeP_Z0P@=yD<Gk~n!9~m~)FZtf%e?+sgXPY{#
zzwZX(HjM(tBQw%UJ!e%*v!zsFrH<;N0`+bmE49iRH$Rmw_jWdym?z3w--4=9^<!(}
zv*cbLJ!NB!Q9jnvVY)MI(cYJQmPTaAM21HyDk?;Vv{VMmqP;!H;4_t2du&4?rOoQF
z>f(Z+q(o+!<$982+==0pqF_G>3L63uXqJ9<pUck{<@woC49};F{Ol9?LHT~L3XIt~
zcY|@(d@iIHvn}pJj|!o$`P@qsmI1+}uv0QSCci_pC*5E!32$#1c%5$+^499m-Ci4w
z&;?qXFYMxtz>mzf#zf^{c^@d+c3trtR7VyzXjN`6Xtod9l#<_3*ihRey=;U;iZ61D
z8A*k06c5t01Zd7EmR5c#r~#H}Yfd-CuUA;e-3iEiY^@urF`mr?dw~K-!9u|0b~i)H
z3t8{t8_v*>3!rO-;O_)}%~pa<p7-Dbu(pt%nw(=RFgNDAFvI2;a|~#pIYxstK<g=`
zRc0}uN8X}?0`fZrNZ|kYn&w-N?D<lb0$=()=YmuCvxEas;UE2jhvuD%dH2dlq8hmO
zH|E{bsMGKH8|K{|D1MQ7N5vPUieE7ABBfcry2(m;tKvC;DVI%Eh$;6JrktOZnl|dB
z#7FrJ%J`__iAuG<q;5q@&MDeyteWml^Rb;YH6&jXL7L|i;C4Vl$)09)EGidZOQC&`
z^aEK&tPv5_tJ5Y12hmK_Ti8otemAEVY<d`Nu%_P5k!{t7yQ-rr>h3Trkvr138Ou;V
zs&(`pN+d0*v-|3nSVSAK`P4)`%F<u8zqZt*Ch8`dlRhWEO~_Z?M(6M+VZ=p!bz^%w
z@l3YW+nKDQd-bTjXj%KXOFMFaY71WGt9vkwu%c)!7G->s(%V@!N|$RsI|m}f?ajBQ
zT}LUUg?j_gT=f>&b0lahts5R6M%=DoAY+m12K#I8H%UJvu>1+20g&g&szPc(UbDkL
zzJc1<$17w@Q-#)7yv$NzX{?a7t!L`e{ZVd33;NEAQqRXLTj{q-`9?vl&%W$>C4vQH
zQH5%&F1jTMbmb~~YaBzaSsk{<UVXASm|opDrOpx0I2Wz6$1Uf)Al;Ew<9uMrYiL%m
z5Ba*=jd?@BDwfmeU}@yug3_YlV0!1|-UA~W++EfsfQpr2u*7btIZVUGpTB!WX7jD)
zd>|z)o`ujv3Mst@l$w(qD1&wZ^j8%s^}BoT{Ny*k-0D(#V@mW?y22VU=5AIj9dg7v
zRC#o7E~aB$Iy$Uaw);JO!9j|4azWK3r9Nx_D@&$j?tg^}TK1sqpbN@^XI@w^vnpQ^
z>=PWc!e|l9|GXB#NRy@Hw02+7Y`0P;`ReXA8)`^WaD9VoK3!18$`f4k0r`GfZ=c62
zlJb~jvCQtV!puUv!eFT+k2}lQVZB{uoNqk_4g{WA#Ft_1sa#&=c10dMPbBjQIIXv+
z>LOg>T2iNKdxC|$SQG{mh&*t9;hCZ^v6S8C$>M0Wv05^zV>}-QFD-14wW;ojN_ji6
zUrS4~)m+f*!$Ma?Cnv8APHZ);c44@1i-NWzn6hj?$zJ{nW-Vqlh!?l}%YAOEV(F{>
zV$~0jSBWe)^L?}`Vf!JqMRpb0N&kWT(G2Acnpa)Aj3{gEp{GiE4<!K%X0Rsqp@&Ol
zosbwp?Ei@BDsLYk_9swv<xQK!#D`+A4e}2vo03r3`YA~&?tBFnriG*?L!?!?S3uXA
zIY9PlpRa(Xz4RE`Fa#g+Urg{RB=|5AcJLX{e2IwT_@BrWaS_2sHU<d3_#&*8)B{PW
z=MYk_pkM0wz(8&&Y$MTD;IlLX-31ecBC?wo0^dm~H-V&F17@j_(GYQYDe2}i@yEfM
zi4V^w!B$7$X<JtqQjKg#cO`^;HO+Kp`%yO@Mqdpf4}JJJ#F>yY{W3lP3(0(}?P$o2
z=gnj#xuC1zT>cS^Lr@f>RCBGacKX-?w-3Wh-yy^}4KI@Uk<kT;=ah<hydTnD$a1hE
zC|UeA5La|`kSV?j`0(kiK2MkQQdH|ZQ|0k&TRAz@re-Hs4ZU>`QVE%#ss#cc*r2fn
zS?@CQ2f<e^rW$M;s2U`)=b0(e#eezL0M+0Y>UGUlLKh+Ne&_};SIOGRht<dMTdFR=
zZ$)r8O|d0Dfp<~KYam0M(jHRX_?6Ym&d-sD{0l|Sg;46_Q@$;=6068K);R-f?=P$L
z094qg1Rv5qr)(J03t;{vL{K5ogdf5X*%V_vD3*dsWXx%9GHuBuYOyT-JuC^x?4&i>
z744`w7&lggv=~I?{X7oqjU_I!-$7SQsYK8LpR$*+%l+*8MP>P)^~lzWGImU1N1z``
zwSPqug*xnht+4rZ6n{thVLoxM$OGA|qz_90>6zal2P-*4VU6?;?P;q?3jLTu9<zEW
zthF>PV0!jjTJ#QB5b8omTeVcKS!pU?`gm6`Ptm58k43FOb0p_pg!sE490t>1VJCtH
zqdQ9w&1S#~gnZ~TD%;KXV{ZA`Enaq~wX7VnjnIboJilds84b#vVo2!D{cl01JBZAX
zP+F72^PQ!S#l8cq7B<8y{Ol<gR#y3X@uX$5(Jcp?@m0Wcxbizj_m<wIcurPkE1tfk
z>2go0)fK!}gP}hIz4G*_<KrX9EV%+b`;*xp9^?Za$}BCi-l1<3ElsL?LjX+byBF#^
z*ybWUmqHmJ)g3|z<5JK+VteW{SX&KyB(nuBGn?MVOa&H#>B90Aw|SbRKohjVO?JeG
zZC4=+&%25!Z?nNP0{cSH9hqszWDJkVro=2Gk>?nR>Ge=FP4N|lZA!$Mh1QhtFtegH
zVkaVsaT7OVjm>PEkURc&GPp*ZX~<L>Q7nGe8i+VoWSN2P1|`~O(+-dIGi#%=sBLb5
z4Kw?-Q@Wak-*c+1491#4Eoqn+x?cy=Xe{t+F>~-8REY6NYh%p8JpLmvx9Vx1o&`jz
zjSm5FU{?JOL8@)di~Z(G>>Z?Rvltcg{(%gh1C>)?)$WQ>xO4d=;+*xbzb5{!R`T~K
zy+@#9!1}r!YR=7(zz_$Yigl&5X;H2e&%^?+KzHu@3kn;681-u>q5mCRDQQs$A3QMk
zZOHwb{@e!KK+2xKQ}f#^Cj*qb1SqY`^QBGS&y|$??E~Nu%F=nj{1JTy99k4L-)YpG
zm%s<0SSd-HDsu%KKQuB%2!yLs858!PDz`(J$Xu}Oa0eh}t^5~|n`E2&Inc@9AR(eP
zfKhh_tr+7&`LB$a`4qEU3`pI!;k3!rTaruG;$V3oGT}A6E9HHDZR#0QFn^=TftntG
zE#Duuo}r<Yt3*n`J75zJTk4_9o5Ce-n6TrQ`dRjwmJ&A=XeqJN14eS>%Bq=>n>Hk2
z=}TI<zz1NFAp(%(-mwFgl>)IfB5nF!F02*@mx5hx=YN8|v!*;({}M*SayJMz9{<Z7
zNy;VnQ+lT7Vm5U`?bCkXfLT-4P4O$V>2`fZj>6LF?24WyZHUJ0(&jdP8BnD4=|O9T
zC7z~(SBk+{yLVOKVtZ|V7+%N%>0J|p9t@4eyJn}}&TBEMwVQPny3Xp)5@xsacD=-0
zroF-o_U_~!FM(=Qij6!q+pnz<Ae)E8Cj*MYHD#o6qa`$R8L@nQ8(IpE;LaQXUUYR3
z7EMb2)6HDR<N^R#Ez-u}`P*(Zp3r`-P!$q9zUK1|T6{6v9F7Mm3?Vn!cFFK~K!K4G
zO4TXi(kuL|qm0GCN9X%k7ap^HtQ!yFqjT|pCg1T7S{d*4dkzL={&Y5NLH4hQ6Wcy$
z-o>BG!iK-GXoRH^lD-Z@CSg&+9#HITI%Kl8Tkk2!^#&q2qxWLPSGx&$NSB!6$1~#m
z`IpG!X;JgEzH{pMKzRc)p4dZ6-&R@c8mmN4+R7F+%q_Eo+DzEhi)RK{BeHZL3-DdE
zI(QY8zKlv=s+4zN6`_5MQhhdM(cZa!%kxnx)ib@QT9x@90q?i<r3rHO+xjA7Yvelg
zMIhyr`j&UiwK6;I!*&GBfwSE{ne7dP4SRz;<%kqIGKjkPlKWM3ReqbcG{jQ$xDtNH
z{RZNswXMhzDeam%cljlXw0YZfY4cjU=~E!@uoSn*;BDoNN;z2guvR2JpXowU^pq8C
z&12hT&t56?6u<$?l|ps)MBv(FAf8M*m<-TnqR9MnG^?F7OSMxG@S<T@x}@h;fjvl}
zYJjQr$x?_mWwgE$DbzvK>?@T*lSIs|Qi!%uwZ1#m$F;t>Qs`6hcCR`@>w8EF(Uz*#
zS1yHqhhj0sN@Baz<kz;@{hmhkT7}I;;GlYiEN%KUOWI;uddV-axib@`OthIBy96Z&
zn=@l}gcLR=2c3=`BZE!v)&g`6Q(xNjd6u8uZz}cl%B*=KX3%QM7o|3k$ALUjXe25`
zJISgQ$v0-lCsbd1>^PdbpsxOs>NTa(TV;Jp<au`k^3hE3m9Zwi2y7a3m(hnYsB|vD
z8y_mKDec3XkKXDGeP4;ZBud8005Z~+P@1=Tn@iSqcuPIUlj$-$Aw?zv+45!(!4z90
z@cyv0)`@aj-y^GbYkiMOAuMt5_JkCIXh7geDfFTUEKwiU`j$$eufZR*zMvG^A);4E
zweO>%`YZ7kzf*6m@D&e%sMn%tfE?!Z{B~u}$@t~K3}NKY9}A4cGoim14N<{Eqm=Df
zemfY2FUACPVDcuyxKxkfL+a{$c_YP@hCY32zI7JV_dtOhnRUF*=PrxiDQ^V&MVgNa
zWyGiX*-AlvzTjiQPtbxCS^;%m?%C>6Z583k@wD*dBu-<CiPAuoyb&|e1dU6fks?*5
z(<6InW?5o1#U}}RQys%llUGeIleU!h#YcdCcsNAdpt5p=t);BAPrT=pc^X&R{jf6u
zHoH-Arl`2mQpy@Yo|Sfav!HF3tbN*B>N!y=-EqPPK{lV%A<%XUkOFfPHhs1ONs7#N
z$@(tYvwgJ<b*nDgQflyH&h{P)u!hL=0+@?dS!7E~9c@^|;SUfJRlo*`zkKXoG*SB*
zz^hNvE=AKc#4@nsA%&oWfn&7mNNTne#IQqe3J&&GpM4}KCx9$Y04Ud-dj+Yhu9730
z@267byLkjwd*c3N{-ph=bZqLe-uNJSGi4RVGnUf<ouBXsCU90M@1gv!B9%MHe}JTf
z54HjHvw$qH*w8{SPl>D*nV^yhBct9SvonPaHJ??Zq&mju>4pNqaw4djw_ZZ^KyAjv
z(_t|d(2s=O2<xz%a?0`B^Kw*sCI*QvpJOb-xZBQeo-F1ap~qJ|+dWsRB~K4Q%<Bko
z_ND1G0w>0^5NB2$^pd{?SxjNr7UDw?o2H5^t~du7$)qq_7#H$Yw=cgJ>Ddss=&Cos
zwn5~&_<OV;ND+j90LAX-!}`Q{wW}jgz<OSR0{#kZE>_VJx)_{H4SM=keP3a59~cQb
z4@N>m21r{EsN{N@?fPy-+m^<M-;!i1!Rujs66v13>J_wozc2y9T2Y+;1Z@cZb1L{d
z0e*bEct9orH{STAsV-oV+|Cym*-?)d<Ed&SL9Gr;<)LnVfh8$wBza9kgt#;I|5~|o
zv;Zn8$rNS?E8xwG**FhE_rC2whLC3@0U_yX-PpA96+Q1>hl)rASZk;N#zs5&BCQol
z2w6IQg&krNiZ0A^tk+3fNv)0^xW5Sl#IH`l??N>nzl+rz{4NjvjK)M({JH9z7Y8#*
zisCgpUJXX!h%LuNLckS!0)aKeCq9>^-V_{Gz1n<3a4;D<MO5q#Bu_0A@z<x~zmj5;
zDSm+zx|W_`xmVH?jCL$N!C6PpbA=R==m~k3jweZ|d17G0A7ZDFSKJF<mBJoab1$cb
zBIpO?LzU!HvBLmF0c!7*FQrf#2Iu)1Mu{zmy|G__m!r2=2QMvUK`|}Ckfg}Z5nal9
zW6$AP63N~`0^1i+m5$g-k#byYJBos1<OFvF(J?G$OObn#1<0}XcE%-)hS`zqYAPS`
zDIJs{HU;S@>QZI=j#sb4Z@xMXzZ2D=_$`oXbB!A8F)2}1Y>*K!$IfD{LAXtiouH7m
zBQ16W0Yb+T`k6~Vv*|}EWgnvt6r34rMjn1O2;Z+xlD~_~&?z}79^Rri#bAmp$0#M+
zZ8*nv)L1jueBNb)C|uxPf=Lx{s}Rcd&tu$i6|905-%E(c!u3JSIeG@5r7EP?&eWah
zU~e@1>|#zrbHi-G0+@gFGsJ^SddMnMBnafC>gNmYM<J|!Tj@pcKT$3Gb@1+jm%}en
zI_{#W!~q*|QKSC;_g4kgjd#)tMp#V^c&dmN`K$5NowJ}c6}GWX-FY)Y)T*L8uR#!t
zvTV3;*dt0B|4OE;gAu!lYQdb<oqfMW_L{AP8CrIWb-@Me609C#V7i;Xz=UH5;9)?X
zg?U(TP`5`0Fl4b1Xg3xfu%`q-Dwp07pRf^_GV#@Dl#Ia_<RSH+>|(S$0V=T{O$?U&
z;tGVV1Ki^NgXmL(pY8EQymn8fny)wbEgf3l#LD9l`3tRY$nrt;fWp*N6ZK(c)x#PN
z<#ezt-O|vcydX1Q)C!+2vLlomzy>q08h`Q-Fb>y+1_#>8BU@h{FBy=2XEJ@5NKe>W
z4)C!9@?4wB1Ec65B*5@70&#>8YalYy0Y>TpNOCw0l^FJni>&vQ$URud#x}zgk8uMG
z!mosXb^{IXLrP?&LypWCBuj5K`NH>G@!yXB*%c>VS0d9Iff^<M>>BG>(hksxFU>(H
zh><a<X_E;*Yplg}<e{o)M<@kI{+2Z$*5JZ*wC3|_8i34pH&tyc|CWfDW6W<QhJ`th
z^&4z1QuSm;n1&}AfG}n2(qP2V8$C^xU$61G=RlOgf(ZA$Iq|Ec4R@R2ciQ0dG%g=5
z=XXHKxh)c~F7ZXCoB!<MC&`BnjCM^r95ME>Te8I@A`VD)%>s6d6+;Ul%$<;X2{^wn
z_Q5!XI2Zr9EatP<gnVpHHsXZe7irEwcL8O}Bhdx3ZBt<zqFj6`^b@r4jUpJU=NB<t
z$r7aop;Q1m96_K&ZXW~I(PP0*Qgw!7O=uXkM|z_rO}(T#!$mQuuC9hK6;E##Pv~P&
zpvX@yGq9osx5RIT2t`#u#LIHT>msKyJL-!}cg3^eAaLpO!Kf=Tz3YN{;N74{J^L!L
z%wOvk6oPDg299F{AJGsN#9UYpU9cWvCeb=y_yfB5Vd%vQ{DTs1h8sSF$Q`O^^$nOe
zuvRMU1=_@nKd})5+QhGfxLv2Pmnn`afu(57)6lzAA8m7t?$#_ibg_tSawpYF##>J-
zjC2m#IbgO~$f<;XBnmTIiFgA&yEPLwl~9?{MiUq>IhffaGhF;xCzXWmHZS3#WY{^q
z3D+b{4fO*oStd+_InAV<J{O$OVw;38kPNO?{cmDZ2!1?w3TP5;E%8$A^x5DgEjDW^
z=k3TDe@{DoCMfoFT`e}wjar!38h`sD&OiW4BWI<7HWTm-FZy}aegI9gg@zv3BH7^!
z53xQ^QxMjrUEGG{N-P(nArP5Z1`ffnu@(1YU-lgWySNBS0|K&Thu`u!nd7vRw#rzI
z&SCPDLhzn5)xZiu;XY)S-rB7@U;eep1S4<gGepqjb1_6#CL)_f<n5zLv=LX~zbL@C
zUS$nGknJm8;C4wrjEEdQ_Z3C++*ha*i{_fuJZVFbv_Ua@PA+%mV?%HD<S_uKI@9X6
zyywr~5&Rl}r4{7{_bHKEF57qx6;#{pe#=&o#%{OP#Qq)A0tT3vRUNIxa#V-x*`Zol
zQ+#B-6-)8>(0W>%$Fu9LSmMQP^+WI$z9riiuE1t>_yM~TS>*tm+c*eSgTKYP@GKrP
z2R)Q(--3)FQ_u&9!*uEI*_LZ5V)5g^?3nlgge_mln^3W-EaLmZLDrw5T=lx5d(7%J
z(uN_@2HEWCSWe3B^<(5USXaF#+u`#mo69UaJRQq`{AgOyrNP~Pt-)Sq`D<DJd%?GX
zxSFHXH-c1kYe%hWu68s>&6Yi9f+OEH`u4Wbx3`VHy)F9o0Q}$QIQ)^SFRY?d(p%}o
z<SIxUG^P>WzM#QT1!p%huLUr6Fp1xtgkC_ysHU!BzzMrQG~52YnI+)XNnaHVzyfws
z)^_ULo=ye3xdVeuVZWkDhfUngc!Pn?Q(~1u&tWWVbYU3sH?RW7dJelao)#%og?NSi
z%$TOFa=pm%mn%RX4;E=Mwm<EpmNAaZwQiC5S<2k4ne`yHYsCxf!q>k?>wq2VVD3Qu
z@pMFuMU)a2z<^hndw$r8a%oa+25RZC6@g+fBb`B<!3ydj_SUfyYuHx#cYt4F58ECW
zf$XqtAqDo6S^@v95t}g}PT5w%Shrnz%QwSOA%{as0j81ONLk_^8(C{k(F9mI0@>F1
zE*(9+E@bW)k;-%!i#(U%6uojJ7QJgimy+zHTwS@y)k5j<zhQ>|2s0dPOAii#4)g=O
zP(N)vPonOPc~qoY%tj|pfDOm<$$)$XFfe8xW&SIyBTxtW1_Sv|VsT~Ys&QK((0UY3
za|s1VO}KRiu%$W|)GvVR0qG{%v}s=fNx@+oK?t26!*7f2N<;x#62C%+0egndmT>%b
zrTiTakUsJhHb(vntRAjE>f;L2NCBnzhqNM7aGt`LOGLD(!?j{la0tHxfFhRm?RoE1
z5e7m~B$Z?0fE*Dc2UW_Q1L8A8SSt`E8`N8=vFWI`h$3oY#6<YtNuy#+LDZINL@4>Y
z`5q%~CS}8Gqwz}B@C`<o3}_HL^GV%;#2Kk=oR1iS+&KkNj8O(2rp%G2=L!=UvhM-^
zP>OHuRxeSQM19Gm-rD#>luujTN0N};VIPokt4L{a3Ek>lkT9V{r5tFlK!zPVFcTor
zY6t;B`!gh5je%5XgNb(oh5heI#2D!jd9Ja%hdujB0qM+ca#L~OumM$(h8?&SfDs}E
zTX+3&4K6?Y4ufp~fO_4nRTD1ELXXE`i_i-|jI6ck-99tK`v4$)W(>*!KpOA;KpOA;
zK+^j_AfI`k(0Lw^J~KA0E&x)*T?nMlTt`sim<z#~+`l_W-I59aQv+;B0LF}Kl`y8<
zcK#wH0QL)2Y$k5!6G*GprhwcaYBrz<csei}PYKS~BsP!?h1;mtIDZ85RYK=!1XEIT
zQ##LJzEeQ*LIV&L&)<lx3KO3Mk-1KZFp5){GadBcbI>ffrja3sBu`Rn=|q|H&R^&g
zY%gM9Kt<Ijoc@J4-GtCd3X$J1&1sgi7m#Zwbu~wK9z}|l(|`zZNFbI!$tXi}+Stb@
zXGFMX+sb~0rouJr0auGW8i1QxYKW;)sJVs~geA>2z4Sol^}9r7V%7$4x*JeKpVJKX
zZAx$~8Lb(;nk>@8Z#SR>`MV4T@5>@Ghcyw!1VVT=7|=SSgbihlNdc4#AA%Ijx-$>m
zVmU{EZ`P+f)9?oTVTJ_ZA!Qba2KbMKK1z{lA<Nl<tm3S|cQ9%(-4IJ>1?WhC?i@#P
ziL(Of{0|vmeTPWz*(CA`oe>+<1Vw`G-!}+G4Pxo*;MZa2CPgNUGASfH6acWH9216_
zzlg@4jR#P_!e%JO+joq&xyD<8@wU)-8)v*NG2Vt5Z!3(qLE?>73w%<wUqkx=e_Brw
z5!>pQ@DM8Vhln?5^j{MNjTq6$FdqP(F+$jmK#?6V)u&YLLHsu;x6UZ|gKLsxTw+v_
zB%_*7{#-}l)vtJ_O@%;$lU2mFZx6NIrw-O|Dh-@rH{S?5T!O5VP!~z8TLic%WqiO~
zJ-~8?peh=`Zkh;^?!5fxMDEjjsc2{6UfsFkXGSgSKtG}k85a_?$;iQss=u06k?MR%
zr^f|}brcBOHlhZ|PgNOkuH;bxh!`i=v7DcaHac|Ya1=ldmysp1o$mk#(4D7#idKzr
zQcu$&p3WH(gq##0?C{<-z^etVFNXCYeE&=(9Gt6!SI)<vpVN*y3gJFfn(JfET!_xi
zP@Lf3QpOGh!etI$xD=kp$HRAlg&y!lp3r@s{lPn+nXJUTFJ(K$`Wx%UDlA$_i_o1u
zK#D!a>{9l=FFdjNuYhZm?i_?zH1HN)wZ0WT$@hUT?EF360_=W=kCiR)d3LY5QD$v^
z)+Fce^cEGVnSRSQ&+gzcuypvl=11jx_}oWVX8JIveBrVsaX6Q>hD%ZM11U5QPy;k6
zbSDC(p7*8NYKmdMsY7pIQS*Ejgk|62WAm-O|GExw*sX%bH)?MRa_wWgY<XXIRspMl
z@;;wOmqJrfhw^qekc~e{-uxl(Bfo2c;=SrVTF_4K^7r;CT3=daU`8Zxv%~M%2_KAz
zEJ6QRZV^+ktD84!s3pIPYy@5~8!7a6P^%@K26)`TTRljHnF-WQ_k}UBTObILsR5Y?
zF#&kq3p)V7^`)TIo$oylGPS|QIYg#@c9%&Q-N@3$%Iu|VH%wHz^DSf|$CdJK+0!kB
zE*Ev)MH^KgXD;=y+G=1z_Q1Y@(|ac5cn*i%O(;*c1i1XKFzUgMtuR68&PPyR49W-!
zb+4Llpg`&E5h$1iL)=XQ1y_Fq1zVm;pn#lyJe}&;7K`ZqP~HYTh9G2}eoqnuO&Ae(
znc{G=L1d@;M5;po1d1O<8jKsd^WaYm45&979RWD#evuE3nTE}=z!ME-rO*=3N%l%~
z2I$nCKSC9(TZzo*_7z_T4e4f(7QUc~x9jl6n#HkQh4lv5XFgAFFiQ-hCBuB-pq;%-
z!wd2Q-hURh!isG!K6*0IjgwwXC$rW8u>rPn1(A^!Aye^QcqkAlTY|%`yU`J&H@q0d
zu&hx$O==sF9SFeA7%EI<(Vct#g@$G;2EWzkX%D8e(=k%T5H^P9s_*$RfwYrd%kRMo
z&jGJx8mh~0fawh*^1$-U{;{lRpLAn<@+)eHFrO$e2xDv>QYRz`<KP9w1dw1v#<(P^
zlv#-dS_==wwX*W4!HmXVP928P&VU-k@)681@FnOp5@3f*t&mRELOnjoAQmuS1(}E>
zY`;u~RB#VocoQ(b5(!;!RfhYV4_nLzZSwdln2hnujnav>s5DR{%IeNP!^4jC!J6nf
zLCcU`{QD>o@O+|TKl6-gr$cNHB8GfM%5s&$oxIpZT?9X5;D-$SF!Hb~xyxesLZc)0
z)LLT+IX~l&J5FQz*#Q{`ZacPOODp6i3FgCEwgFF(ObGA-xFRIJfk*@k$n5<p!tgz%
z@t23!^?1c$dG-O`UHlF#kS}roQ`qWZ=E5p}DNJ2t<}zeU(pJQ80~88&EnF}?9#UAH
z7h_^NPP5)K!Bm~J6G6X*)hc<WQy6%XGA>yU^bgbjWliV1_RPm&Ty}&I;f41Mf4vEd
z>d1p;x#l!!Z_Awot2Y5Bz<et9GVov=o%JS<&W;4b6<m*m9-W`1iAD!w!+7Fg>>4~w
zzQ}Fn_)v<aRK!vuFuI*O>&5!GC;&q$r7?LJ(Ex{L1z3cCB?7an-~@aclmLv*;W)Q9
z*KnAhnefYjuh>YeyWLC1Zv$!O3MXukKY>Rg&3yPT4zNICPXSuYWZ}RSpp$YrH(=3B
zI>HUliAF~7ySY%Wb?5PC0az>7Kf`HEOHysP*q($71`M2X+=<^^{Dm8n^D>xMY<mn!
z>oQ>#`zvbmMP8<J3O>)6?;>7ir=?rZ;)Gl)Z8^YVhrLOXNo0~V^hbpaI2Sa)*IzV<
z!5+hA6?Q)x;ADlp4t}7&>8p!vN1?+m8%K)iL+3TUAMt2fmTo;mrXv*YZyY<z10f)f
zw{M4`N1RL&FbE&$o!k!gkkG8Jg^*MM#iIrkyL9KF2qEBC2?Wd%P~a|$TfdS$Uj;Y+
z4^SlaH8>EyTm-VT^ChCKoH1?C-||lA`bH9sf=Y_sm7F^+TC3!Q!FY6MIoc;Feks<q
zk03_uIL%2!T4`fHMPoxZL|boRm?OnG8QD;$@Cu2&IF4S7@Uvj97*n3@OD7UHJ#Uc&
zk6SdCM)ktW+4E5)>})C08skW;sfd1JRfSqcV4P#|pGBiIP2ZC&85>wKu`gz<$FymW
zVc?qB0jwk=IS(StuOB0HQ9A*CJ4FQHs)kPQrM^aTUdMy4LdVe5y?7@-GJX(9g^%`X
zk!4yn9&xO>zS#k7TFJ*~P92MaQxM|YMvKNIjKab;IWjX1>m$TdpDyUD;L|=#?cDQx
zxl36WJLqF41wQ$AfX{W>v>!sRhCA39G}U6Oq!)yIbrT*zu=bEtyBn{VyRRMw1o?EZ
z1(KN<2oNrXh+QF3qr|}?u}|=k0E1@;)RO??^bViSqYxetYl`PwWj5arJyI!752nTc
zK@qS<NqjfO;Zg_EF_mz-z7O>lQoS3D1iX%>*Wcka;5iYr1w34J1=tB14A9WTvmn(V
z)JQb!ir0b~3)Tv1l;XkP!8#UE4;fM4rKsQ2(zdkrQ#I2-%!IMf!)iYbUeRK!z=Fw)
zKFZ+WcAkv{8H*-b3*)If8F(*dE$twKqpZN7_9lfU$tDmAWHQHSzmx8`puMlyeRxUD
z8NTx<^%`8MlV=JuRy%JL+6Md_4^vV*e=YI;V&ZvR%*J*;NGzk<c{9C7a-PF5<IAYJ
zux;r!L>Y^(6i*pwLl);9Yd$CCpM(Gu$it8q>o(0rgfH^FR?-jRkih}gSz4(3JuN{y
z+2Ws0L;kQWLaIO85zeVbK(U!Hr~{tPr6r|xPuu-kmM%A!WMr0xpUy@^5nhTj@iT>D
zW+EnltuUw<wp#}lu54mC*CPVnXI1X+Ng+RwPO@<!+Ll5dyagf)tx9=;-}3d_COftX
za-~47@Y?aTOA*W=WVrDwETTjo2>yHnepH}73OD6*%(e%~vSn-7){1~X!VJI<ES0|j
zxLjRcRDE&C;n{vJ)#u7>%tm`-@YL`$RfXU%F=jDd$qs(wBh(thfxM4atx~k_=;|W;
zo>L#jK>-}@eSjWzGPVrXo%0}<$r;rjDF4h4IRqzE_>zq+Tl6X1SKV-i8H5hF;W}uN
z;WKCVgJh0P>m>}`UqMx-lDONz=gy7`DnZ=Aj_s#I2F-TQ>8fW+8EVB)`bb%HXs%)z
zvy)7ynnx$kXwNxyQ1uLZb$oSmiM>XKA|UQ3(4t@0!;eBQ^?WAz;4Sdy9}zvevAEII
z+X$tlf~CKLXlj145-!AEFIIm+s?8hE(E2PvD}pc|&Pc#Y<CZep^pfnj1LG+^iSjBf
z7P14#`c`03(R7Qnb{5`Q&NzUnI}6YRR1XXC(?%x^S!jUR<Xno=92YyY*Do3(V?H@Z
zV0%bDPF5m6B7(=qXsfeLY9^L84(J^}qzuqFTIL!=g>|G7*8eQ-g~?ucmPc&=N)#4y
zrL*c!7vZ%7?_ny?rioKASU}w*l$$Yk??4A|9Pm(Z6wM*XP}9_D5I9i1+xfpZP<3RU
z#k__tB={_Ht67}iz&Q@ShyWliX8RA+K;o?dzO5Mu(`8Z*Q|Z|#UG13`Sz=a8l=3fy
zlBhsADWIa^bShIx>p%8BsKs|7H)5O@p6}uZ{z_eKu`A^`jo(SPQ2iTPdYQ~2Xk;?R
zfuc=#4zIw%l@JnP5QdndA$YtOI&pwepGIbW4o*ra_$3vLnL*Nv>o??v4&x{|`C|8c
zoGpT%iL5<Li-V70XOUZIHwWF{tELCSX?|_1z3_`_&$!?a947z5yI~xiJ=2>Qj~B~&
zDe~!RI<BBd$5@g!6jI7A{wQ=cbbRQA8IbA?^{At2zX<+^xB8q*9faSE;IFBYjOJT$
zT!1_<3wwYODf9`TsP@49wAzyqw4rGHn24v|l|gpc{o$!@0#DWl2|^UM#VMN}t@g}Q
zQOCI8O`+|<F||GFU>ue(R~L;#HLNq9MfV@!{QL6_tb0!^K16S$_6Iem&qE&w<l44i
zoQ8*b2af33r@GWzr)H=nK*(fib1Pqa17Sx;FK{AC9H0}Or-BJQ#IukDgfvl{z=7Tr
zy9e}0v_ssBqGQ7lM_sY`HMbi%v682yaKDcZTo!4I%4Hl)GJFhjNzS`SLBh~qa{$=D
z(D(cuwMVAiupKkLo_4cg6=(aKZC4PsbZ3aHKy1uUV|aw8eTgYS>uq4xgiAWWroe?1
z;dw}!4q5qxDCh5z=q@MCogBF7Z>-`uwsf9S9)K<ltK?GHU4|XQ)k~F7t+(@cp{gd#
zNm%_@VcSU7D|F~Yt&gBqaX|+_DFi4oNZ#NJj~S1!U^|2btcz7+drsK9zh$l9WjTIy
zxwP<8Kl`g3QQh#N-VwZBcmCHi)L~d~wyN1Jw#$)+26g;$-FdPG3T4hv#K0CP`F4eK
z(kV=?_M4Ce+lWD@?p&HGFAOO|QCeZAAuPvZU(0e1fh&W($-tL^@B%FN@Kb<mE|fix
z;!TBneK^(&4Fs`ylmwCgGc>J~bJ_Db_Fup?o;^<J>Lwts>#u^!i3(uZTuc@kC{?=i
zUX+zRTgd{ni#t)!&%OekbZ3+*WzF%Wo?U7NdN0)mh)~X7i+I9-6q<qvUy)07D0%~)
z!M?<^JHH9;MCIL7r&$2ghx{ZXQSn?<5X0@Bbn%Wj6x+&e&;vx;R8ct?svy*25DL_q
zPlt&X3YClw6Af50M8?ec8A?W`k$v{!x;JV{t_ugslkrBm(f>p_*xGPx?(;kh;Z1bx
zsjy9VzEh26!?ua7cwkPBCwHd;c_R!{SQdjt!@aKnDi&tQ8srp)Y`|~$s)4J1-9kyL
zsS<6%XL!LAsXKNwk`_vEo^O0`!7+uM<PV5bIk1KR`|uxGV@5evw;sg<<+hD))7zfn
zDe6#iSJxUHO0)~dym4bhM<uSlz=6Kx>ryLn!4SF6@7X7XN>ELJO}Cd(oj2jdul3o2
zIf3xKc6c?NiA^w~%!cNO4R|#3`l|$U_`m4EZnJ79?NTila5yIb4wf?>zp`a}8Qbpj
z>{)rWKYAF)?6vjCB9jYM)KM0mXYOM;y_g%!_BDPjI7hsv>R`<jth*c7+ixIiFuO&g
zCzy;WzN}`-I;14yYAEh|HB+!AO~r*M?)I7~uz#lFYAJ3?%@in>sW{9*93ZQif@NMR
z4(fv`eo4&~nDrWhnMS*75XXK(5Qyaj&U=OhT+j*$Ias5H1tMaf(6XSxP$>Eh1K_WM
z$6)N#(+OBlD-O%I^3lkg*ybdX3wkGSezg7a&%i6Z+X_s|mh1oRqlv%B$2(N5Y^4{i
z*+NK;FC$IAKzBa4ib#R+tvdq<`Y<dC59!YOs{Zgblm)qAKQ<DFB7%H5ivlny*3*Qh
zYjy+Uap6W`qPc+Qqk!b=41~uFMr;1weF$X}SSaQtp@B{X7~S@_hWr!dDGk9MMQ`(a
z+Ei=Nkl<HELr^@50f){Bn}AoFwx|h6RLTzo9at~iT~Cfs*11}jH9kkIT41HS_YLA%
zU`fe)=Z4dqatVJR=q^uwPQ1M{j`HGOJ2=>no-1pgSTEx2B`3YT2)9t_NTl`OrFZO)
zsk`*PN50rIwM}$5GIf<6!sL5%E>7?unb^uRUc?$#>6tOz0mL)p^YFjFO7Ey}!;GG#
ztMqpAOtgXO#(L}i;I2lq-*%PWsrM3g!~gYFdH_-^+F>!o<oR!|()%n%p!{E5rS}J6
zjKsjeReHoHwP`D(Xp8RA+mg6P&y~1GkM;=-J_sI%F%Oqj<iwEp_dnucIN`0JJF##B
z8b+<Kw95ZUM>1&W!BuWP`EwVE`GKE2@&k2=0lpCa<PdJWoOT>gbRiT2ti%JDKAS9P
zBXlt6!4-kQ5f`y|vc~wGwBRXDrNLc1VJodCmL9*Mr^y^V+|!h%I*mL~fcx{rH(#V6
zu>+i;A+NCC*{P2&xz|%)YqnP7A^5@tI9UImNWM4@rv1nN1_uw`bUqFW{vW`>E9n=-
z0oWh@DpL3924H&3-y=QqD-2wSA$#RRJ<)Xark<!-&01s4^y{s{C%Pw^rb-nI5gLb2
z9(-$}X+2S^nqx#+MU1tKwfdtmTX2>Uu;6kxq$?uP?$_Ib-F~ery$lvTY@;+aNn^cm
zy3Q00prPOiilp0V@Rz*r7r}M-=f@_L3zu<DrwZXdp9uva>QcgTS0Fr#V{Bx0Q*0j^
zL1Z@~`-1PGv9U4oY8Y7GI;G|mDHWA}sYit-Dc71Q<@z$cN=>vH?*QX-I9pMUdN1As
zEZb-=AT?#+|15ie1u`AfST0`u4vNdAI2Xm`0W2@YcTqg2cmpuKm14UowlDaazlKu_
z{+d2|NE!jzU7hVV#WrHXezX6;!8*UC^+Ezc2qbAF2&8DSv;jmC1VWrOMWiHwX7&?E
zi`faM0&(Vk0^w34A`lihsV4qO`uH;Y2oo@P#E3w+%4-(bw=WZj8)h^k+XLYt!S@Au
z=nCBP`YY%IJLPhNKA;7WB}FEKKG6a62_)Jh{Pq!kf$%^kP(M49h~VcG*F|xi6bCbR
zOi+l(Hw%Oe7?2qRvLkZHe@CB9pbyQU^Z)wCD_pebrl;Ry_Tg|=#kw`5sfYHe55AfX
z{MGB{#NR4Ejs%Fm8hEUM7;qQ12Q1r_-o5_9J^u0gRE+7FeJD2ztL$5q=n)6P#Ry-U
z2w#ry2qQW()Dzr@1)3R$8t{8g{GJuRXT<Mm@q0@Ao)o`*hR+WS(QR;$!+O|Glkys0
zotf)9bzR(ZbD^yR$2Nu{O^AA2#R!E&USq;d6mp%}PuF_m?ixBcaRk)`2iFbZ8>pgj
zKtud5FhXqy!i@cjQkDy8L&ddEa8T5QZQ4CBFfgyZtb8VpP6cqGRe5V*{2qUK(`{@R
z#tyFe#qG$J8TKC8BB|N%K(=UI-MBE((i$k-j?HS)k?xEA3HrbA6)R(M5f-sH1;fJ_
zUj2&!z>r$Y6qGR<m+<#&3+C~R|EAYtc2KWl>(CWK)xN@p(%Ob*Tm>cF(SSwQ3sCo$
zXY&^1GP?Utv$+7S3+DJ}xq1o?3CPlBjQhs8ZDRqdpvw~)WW5!2tp2FkWLn`wt{bax
z1ijgW+oD>li;C5+&%s`DU2u@B%hotHf@YZcztaLfawq&I+r@oRKA32eMkFn9{wJ}H
z!95mG*1ikBmV2%Bw0B!k${H(t<2$y{^<)(??og9!KB0@?Km?YFloqTVOw~9x(*WgY
z1eD*bdec<0C|erh6Xbe*HHbK-6lS;_AS*+@+;5dH&xp^dHzzW|u`DV_Kgo(7&WduU
z9L|ulnzEXtO<iN<uxzcoN@f`{n`O1^Wl>z}nAH)nX2@YPlwmAR!n3T@4qQpbF5O>I
zn$<yCFIW<KQBfM6WfwZ_oB^84k>7$2hSXj{J5pFJ0^PWIDxtvOv{g4hMtTn^G^EHB
zD9jAynam<H{b7srmW*}QOn5`0Bs`%@?EFP2F{J(Cu<E|>t+>|0=l(91(&2Pz3$%{#
ztybYH1>}6w0=T~wErpk3C}9zuxH<7k8Y(qgfqE0&n|MC2ptk}1!jp3;It1U$Xw*^B
z8`bq-+KDD5+UAHoJ{{xP_#2R);pjcY^qta%z5a~`4>6nl(jWIA+FN-Un2&ZiT^$t2
zk1An@VreB#uXWuFxjZOXY`oway_iKELZWpYIgH|#8WPT5fd{CWbwjYkAZgqq<TGVT
z$luYBzXg;ZRKb4-i8?$x@xM!m4+!G$tZw}83wFkzhY0rp4dAEvj}pXfMG*u#=}i>E
zlhaE#{qzMp3@JDp(-wP|n9!!!YdFcCKtt*=03S7<cS2(<D{Lr(p^U6E0qEa(e8~fX
z1eBJ*e*zw1T)?J&t`GSf{+6iA_LEEF_5_~S^=A&D@l@ed%i!-D%kIV8D7LE>IHxM*
z%2Z$(C$fv_lOw_GO<91tqIgy=tdb|NZY!6k3Qc)$z!Jp_^A5w2`MHB|p39Vr8Kqvv
zW@W>3w=$E-c1t5Xb1Nm8j-W;JN<HnBA5#m4({BO-()ZyJfTMoXpC!{#8-EPA0^!D$
z<zoqmvtn($4l!gTk(k$w`PSQ^b(t?*|AK<>eK)RzF6@ciZsv~xRqG-TSfC`kJY(G0
z3R(GRp!^f86-?VqrrWfsT_$zrZ7jR1N6yt$2mh^1hBug7^=4G%)=m$rx(=E5ZAE6}
zLKm=1-uVQ`fOC*W<Y7MHBeFt``A@vh(A=NkV+zz<{JD)#KTZ5IppHyb!gLBhN$~ZH
z+}F(H+(K;XA8=cyrUh^Am2>SVtlq?m^Ph6m>Z>O5+2{#<h=818TKNYGc@hRCR+1ZP
zcuLZ`&W1~J<LTOrT$i>BE6y1Xt=uk}B{%gj%yKCM7I1FJtc09M=P-wx;@2c`Zo{rb
z{4!}%dG6q)@JDIq2eI-&lRx+43ZTwW4Fi0u3EjXsxEk39b5oau75LaO7(ERVQ2*Bz
z>a^KQSGahl{R%FlQiLoef%2n3?lP?EK?!bBAA@M*xTZ%_=VR@>W&^fikv@mgSvD6W
zx>457nS;Z4F@^(e9!<bL5g9Sv@lmBPhYv@lG|+LRkt|ETUci_K_icx$W!Mo^yb%=}
z2Rp=pZ-Y#<HmAB#<SQZ<ok0b^o=fL2<_nsM8@QT8?pPXXNXT6==KAj<cj3TC)vGYz
z^<blv{Z)I~ZVpbsPKwx{)0-6>pN8Y@ZEu2_k?dBGh94Ovwj*$bu}ymo(YSOBn?at=
zD&u=12I&9~#DA4xI)QJ9QjYsG8(^5<O1oi)Qm_o%dvd|6;Mnh|p@~;h#q6}gCgWZ|
zb(FT+ZU)<Da1Ajnrj%WLzS#7+63xTO(sQ=zy@V%3w&=ki+>5rzfKBmyScM5BBv8tG
z1-c3rqvEC++bU|(0s}v~r%!m{F}z_u7<1FW(_NVGF4%FzJsG&qE&snT7=k0XcQ`Jy
zxqXZ{J1Bfg_?I7I)&p(}7Vi@$pklvPbruuD3X}5F8}r2cIz(B>880aD;qcOGF=Znj
zSh-hR0KzNqw$3OQyjGBbMzuPUupY#fZ0&pjs^Ev<i<Kza6L<K-^Uj*$aEXThGg2`Q
zb8bQNy0i7s<a92eK{9|SIHyDXBs&px4)$b~q`KvhqD}pX&ZW>zE3{0EC`0(~3EeFF
zqyC8rTrEJ|C|#tTJQvL2w+VnU0Db(swQVaVd2(EvA+4?uSa#+j3@(bh)r>oe+U8=#
z(+DANw`*PA_&A=0;uosBEhegtyBZU&(6~*I+9P#w0zZh@Zx#SaO#CQBII#r_lSgAN
z&?SV1AAv&&FT{?|5?5GB`rp9A>>&Rw<_DXR3*&uH^chfg73ww`7c2_<o;P5=^+dgD
z4*#A=8%O>8xKO7>`laEg?LAS46bd7fRAue(IVEff&&UP8Lz>ogRBKHG$NRmwknCC>
zC$k?;O=8yI=-G$H+kCpfEDJ;X_rN>3ED$mOa;vz=jJT^5f;HE~;23|WBY%+tF3Y$T
z(!xsIdaLIs6sT2~;<8E<f2;(#`r>zMZ7x6%yBS^6&gtrS?c6!K>TwsgH{d{0_YNe-
z0Ag6O8{_nm9n-&~pR(PhjwsyAcERH#jh}=}rJZvrbd)qYFl!u^E~qodhrbK3FkPYd
zAuHR)k4~qiJ!hrbZOAEYKsFjM7<7xl2{8Ofnh5i-u?DE{K@)J{HZM?hJ}xT6b}>0-
z9#A~*2Zshc+m;PhJUi92@Kx}>1zfNR?^G>XhK@BmdbN6)o4?<XSSj`2tPlo)7sCnj
z$QD{M#Gh1{anXoSMLB<wgdc>PT)b$QRJ#+kN^cn#f`}<x;fXE_D4wseG37bCEC;UF
zw6(E|+p&$zA3<w|HImOmkm1$_?AE|c4W%>bNjTsn<b2%9*+g}fpswXpc^&~v1LvE-
zP6M!_GAX2>YXd73*LBnl0v}TcwO9z_iHx5KYV=#=VjoZhjGlGK6E+N#GMiylgfSF2
zDIg!p7mz3msZf~kn8*I7?o_~baC`jlVxyc?D-jrI^I!0pi)VGG1L<1d52V^&YUG>v
z;kcTV--=#*O9$s|PId5+3*nwa5j3xbVUr)GWfsj^ZNh<#fEM=%&?p&j{=rM<AD{-`
z58XGY;QRw*pKZ>I7$D;OgWbn+T47ri{xyY%%2>CLox+8mxbl~rt*60Z8Kc%&3-(3o
z2^^tDQtz8odwAM9l#Ab_J6#V`VonWSjZ+T0eBqp>c=LI7Nueu122>@5=<p@ZJ4m&(
zpTvR-;n)SMO{s}3vG(4NyM)T-ma*nhm`Px@c{rCqEZ1e(uRFUIkUr7n^L%1>?91=c
ziG)=Pm3r7+=x;TgrkCG?vk2~#_xFuSXZ*}mE=j>Eoaf((t{cY^z*9~ecW0%JB^YOj
z`p6$0XP5IxV!|^3Qi^giAh?Wer9r;C%+kPJ*mO>SE!+Swv7xTy3FkN5*9fRljWfW?
z=Hq)&FgFW7vO|c5NE6=nS7HCW38s6j)@dC2*uzWE7Wzr{Mmm8qf7tnWf-4sPbGp!D
z#f^@4;X)ZVNJN-}V|~BZJnup-+7Jf>`vdUiVWj{<<dX>y@Dv{n<x+wM?)Rt3b$mC!
ziGYEIRAwhfafjHL#lT@0I1B?P@~|W6^G1&1{jy&$rIeqz*SJE2zxp%O7ILo_T{CXF
z6O4uY#EZ~=0TOA7AqX|j*nlu@8G++1!N(_Ic&AL~1Np`PH@x{|DkuMADb$65mH56E
z9rd#FihY<KV8Z-<Baq8y8vz%eVFdE{bR$r}i$x%dUuQ&kd7cqa_*f$_lMgonb9s&t
zn9r?7U?D%fS2R_`j~js{JZ1z|@GcQx)#xgJ&j=H_d8-j7Lk)k&2opN^8%B6Nh5y|M
zze?d3jPM&2UTcK0QD)-RM!12(su6Cb@IoWpLE(8uxRb&&jc^x*eMXp5xX1{1Q}`Mq
z+(%)T5hh0lKFkP{kmYtGOouV}nLX5fmP_GoBkZE^r$#uB!ktE#j-2uxM!1N=4Mv#M
zbpEChRw(?c5uQommnaN@DDI7g6>xe#oih|q&R^C;bF}egq6EIo<;i*7h*@C7K<~}@
zwGs2(R83;c(4_9K%b$yk)kemvjG`{YEHh$87%_Q>S!~4Ej2Li|obMSiCpwIAfS9>P
z%wZ$Oi<sMunB7K<f*79>^Df0Cx@WB63SjI4fESuO9q@<wHgl&N7OJGVv$~kB`$%05
z0~@DJt{Z|+xCk4l*uqGeK;vWrm5|K;j2aB1;Cd+8e@U(<VSDVvXO-ZdVf^e3x{!P`
zfj5FojF(WN%~zKZ=PA4FBUBY>m>24uu**IT2k<1Iu%_a+P8{FSgSoi0!4Kc1x-^&{
z0o^rzI{ADg4tL1&;&EjvH>-ohb;6%g)0Wb@Of)RjRzMhts_?xG-w++%2{Yp_!1T!v
zpheNK*yG5Ouub$o2H0ov0nT>XQyR6#Jblfuj46%5Ilv>pxm)Rtf~%T>|5(>=4!<oj
zETf|4V_mAKIn^gEZ-?m)D_so9#^4tJrlk2iVA-o^-JmcmSA~uK+9tInE-9lL6s=Ql
zg3W}iRxp@f2_yOVgu#3i8O#%53E?cmcy5L9oRO6!QP}9idGHH++c@gNFxd0WQ>>Z6
zYYZD1;(}k2O%3+6;8-%BNk)2h!iIKCLDi!g2&#3+lm=HyW>!3?;XVZhAH{=hkzfEp
z%qL%_BRCB~%oty0Zg3Jh=OVM*PTD6)G@|}8SsoumGOTuAA~`*-(QE2I%ZAOZRgv0o
zfY4~YpEM%W-#-F6h#f!>sh<ec*Rck<&=FAVZWsjB+d;G2k~BMf0ipH`AQZf30h`9{
z{RCSED`U3~vL(nBjb{^Tl34%eX;nwX&<CNjG24ghNbwSP$>7!^h&WkX9<s^mz)2pT
z`wFZ=8|R7DtFYC;brtFy|702o^8lnIHj967M6e1h)Vz0zkNu=B_a&iXoOWe4RWw8=
zT){~G@&-~$+2v%m=){@6@Jd{JhEuNW2u=t<HMD!SOQE4K<|vW7a&@QuKC(a=9{<|P
zT==K`RMdP|E>5iJ&KS&zlw6HSN)G;@1#ZrGk@1-&bw2KU#6iwye~$=Ux{=bpR^uSF
zL<bMiNFXDnr!D?AJx%i?C+TTqT!Z0pYT}6A?PA>yr^Cn!bNpwe44x)ULi>Vt1w&L)
z`}zZbWPQXFp2UR5nrJdfk?-QiFes>lTTG-yl1T<;uS3+tfk3%f!L*ZdR|0<roL<D4
z(jDhl52aLhl1UZr@-S0LxN{h4p{G~H!BP^(bSw`pc~$NL(ra)<CIG};J#^MjtR6B^
zRFs2b68xKcVqrXe#Vbw0Yx;{0C?-z7CeHfpx`%p2#<9DV^8JQ&Yf?K29Qg9JsM9Z6
zfq@l_HQo6v%A>S#Z;>B2HTrSsCvKtw-3CGHb71Ei2M=qC2{X`5uS5=70<*FL(g#f(
zuaSq9qz;I^f{UCNbkU-ePGeSyH3fu(B9+2nBj@s81Kr@(IPYkM!_;NyHaBC?8Rnpm
zL^pEItOo{ZAqoFN085VOw9{8?+x-VfczD{h^Y`t-sFo9dou~adY1rYte@X_)C-D;g
zN95ukry`BLCoHkat^+|Ult!ADNxM#gm>Q=@rd<yWABUWAODi0!mb&>%sO3T_W|))s
zpWdLs6~AAR{&>>Zx2x3^oZm!qn%=cM7u~)ZJ;H7L;$ZTZa|s0v!HL?mbFZWSI5h>W
zo30f?WIK()Ket%O#1(&yUa*Fx7qSa@0W{s3cfQUITpuKF7+^J%++ZuQI>c91A<onJ
zW333!Q?yfE%S!;pD=#PA3~LVoLhLOA$vBmXb8G~Zf#)ZSZI1vh6>G$H{y2mkxGla5
zbh>L9-HyWVLkxcwT~6BJ61Kt=PWktdhzX`Uv+u@8#kalijz#hNd~Pz~#2k@e5(z}A
zx08LsCm+RE*o2Qb*55bI{5i6oEIj0A%^tg&MR(veIJDCvDv#ku(%!>l-e>`Sc$SBj
zL^#<*cO4l~eNzNZbF^uDUV`tI6nY3rHToH3$1TYS!-m(j9<$-yVW<Kp`z?zI3%mX7
zeZCH-anSK^?w$SeKWG9tqf{>8>)dSH@N3kmJAa9Ofr!_ks`X?SjpV$DY@1GFfb*Nb
zt-{+xg*i)*lUH`3a{5q0-_&Kdp!j_hc|S!)oVUFqU@Q?82a5hCi%voe@_DeeTol%$
ze;|(_TQ-WIPc+Pa11J59X5C6z%bSdB;C**6U$dPr`?l;qMRvfn=260e16n>+{ycUh
z<E0y6*?<S|lXnp=#o_+z#W|8|l=4Hcmik%XZ+0I3i1^Ozzd`;laJztexOC&tH)_$H
zABvJR++h%(N#_LS(!iG=NXXDUgSsP&1;N!33Hsv|xF4fU`}9Q+8y6`Noy8us!CYQ6
z%p~xpH1<ct$&1Ksx%}8R^abt=@C3VJ6M|ve>#qU!u<a#!U<cV2!R8A*1;)eboK(>J
z=U`%Qp#NOMF@9}}VNxzf1^ge-)^VyE(=R};`|*mV{P2u^<^@0q9QpIl1R_sD`#5Wt
zo(Un2&NJyZQW{wLwxzR$M={h%MVj7$FKv;p?hwlJHXx@%-%Y`hLViW&V4?Cs<t>!<
zGW7~8|6(PI4;(~B!&KPHZ=uG+w)Wps8@u>q@ru+LcAjq}y(*IaM%8h(nLuqaSdXwq
z5<v(9$rAxWr^(~O&Pkg`y`6e1(t%^>I(htVLMN;1pl*VvTJ=3~6aO<tNq-&;ax9;8
z{s$}-0NJDK6NySV=V1zmb1IC-BgSJP9%3A@oVyT=)roSr-i7vQ&OiRh4v1~3C51g~
zk9H(Y3elBhBJgjfM4&nufTn~bixm2i2w2rJ?Z_bY8Vw(oeUPtzow%J?$6OBa-EWQL
z8(uSRt=of|u`%>E_$%oACLTiWLFz7vf#{U>M<eak^U|I*(wLD($179i;z9mA_03?)
z;-uFiVp(k6dK3bqhc|Z|7VhGEtaQ6$6o=#!&fAU9vMTv`uS;!|EsefP^$<SqbB#Mb
z79d%TX3zd=K(l-@R!KNjiNR<VhYxztS{aVaWXh2;3%?X2dk2o6*m0-r7jQIRr=7Or
zMzPab>JaU;Rm~1ygusm$U*(El7hs!TrT&pFq-ejTFz$1-2Z#FD22w^_en`J-@jq@8
zMJTbD<z%2&Y!A6eFq;`+ODj2t<9;`>>-59*C;+a}YBw%|D_}XDs3X3Qe;@mPbZ`#f
z(T9a^hkm#PQq|=7D44^3Ms2a(vi^SD#@g}le1yBf05`taYYko!2n$$|6*oQz=*ag1
zJP3!+ig5T0&kMfM6VCbKUojLhK)*ik3A-%pezVAu*GcxP_{eD^$Xh&1c!%R2s5?k&
zJVf>{m*InKeDf)s^DfoXzjw=W{(uPnyT4!%fMq)%eCdlxYP!%dFhMWEi^vA&C3QgD
z)qwg>%5W@kYc!5X5ydSDa;VBOCO8(`gxDYie2Lo##H|VAo2go~VH0h@>V|tZg|$9)
ze*)AHC<eyi7%y}Yw#PWoKu34lVwIT6q)*LuI|eRG02CZpG7AsMTgDO@`o#4Nk)>wb
zgIrA!@}Qc}$YX~P#^kh`qx#L_#Vx&Mj&?aniLTMj*bWFz^btd9DxMc|!4zR>hG?-=
z9g7v&FenJ6_@DPS<gF<-0a36>{|HlCte{G9(ukSqB1L>%1Chv2=0_RU?@tga!c9BB
zkjL-GM_E~iJibN7_gwQE%gT@Y@;j%qz?-;Y;*|rE_6ro0F@V^%vhv1#UA-OCYkdIa
z(&-WFAmxR4h5#%p1z3Es9Dzp^+nubs0afQW$~f}LKFDt^D{r07d~03%K8|ENFl((i
zr;eL?{^84So*oXYb@|J|?Dth&33ISIj`^N<0ao0S46}SgrOoGQHZq5ipyYq>6fWi<
z!1i@bzufnxOQsDkl*fm*afxCi@Vv|Tu52K`5#Jz)cBSzJ*rcSI(=6wh^S<XmhsJ!{
z-FSNXRt`^L69_jDx&um*=alr^{XlQNag{qAu_`EKA1cf)zvBXGV7eveCKsIFSmQ4c
zg5yWi0IX8i@txdOEMWG1;>+)nd-qLevqQMXfi><s0-Lm)wMQP`gmFO>njS_{z|x%h
zDCoY!Fl<<=b^!OZjh08>T7V>LfZl+ED{1%&o!`@1WoKz&AT@3c&sz(`?1GP<Rq?d1
z`~<^c1z0W)$POTOry%xeLF^L%DM{?Z#uv;8CL(szKSAs#62!(mJl~`@QM&`w1|9Yt
zX6@4>!|agbHrcahX&QD7h~l%KPg30NX;)p8m$jcqZ_1e@_g@XrQsgfAAIKd%2#cHT
zX>imOt@H+vCkZNz`Xqh8yySg<7X*4=5C}tSAceO54-{%oQV5hWB+)-XoF?{B>=DQ~
zX8Qmf-2lroZ8O5sS{yCG;35#WxDd>56ysCcwAk$$i#uR3sA%RB%&ZfGQ0{#nJ<IP)
z!VVIS#{h!>$l8+tJvpe7gA7zL2A97aOFxWUF}U!ZAY){;;!}qhS>~|s9Wk>0PkZMA
z5M`A%{+FxB#Q_zC)SMK{q7*Ncisp<A1qDh%WtJNVgOCW*Fr#Q*P_UqpvbKxuwuNTp
zmYcO(o3)nU-7bb&o7<IcyMt6qmo=~P|2^k@XF$yA`|r2ke*gdW!kOpX&vTyhoclS?
z*#u|tv~CNWb!^eco~XW{Y4e0606g#8f*M<Byv3rIp#K8HhJixU!8>g{38$)xkop)M
z-+rkLOu{<Tdj%E3Kv~s^eSVzvdI!!cs2F>!`#)l-lM0cZkJR4(BF?hWTO&v&PAK%i
z6t}%@g~uOAsKl;c!w`NeZ4nKgkW3tH5wy%4)^kVFXC&BaCk59Aa{c_U*&Sr74OHv6
z9ikBA_~8GlKH%54{oDtfrVq&dbEiI_jAbb417-vNKkfro!1e#3eZWn!xf^l^vz-6+
zeZaw6I{JWp=>H$+0}?@#CVvdzq(0yrLH~byAFyEg5A*?fIR2OWfDF&O>9yB&d3{jk
zVVpiWFb^P`Ao|&W4A0sG*&mjPkz7RO`hbihSra;%S(m-4kj{NPry{T#ZS%BZ;tcB7
zo>tT=h`Dp0?LGc$d8|n8n~LNeH8?O{i|L6AYyT6N3bKXC-X|gzA`z(&Ha^@HJU+@D
zk{Q(4>b2e$4MZ%z>5d@`DiO-hug$Yt4z1h^VroKUOWb9uo`gwh{z^`ih7mJ|T6US1
zHxh<NU{XCTf@xCnG53hp?!;_O{F2Bkk0!akY8_a4bnKFWRqgTRrpkj!)}SNSnx2_K
zd-0;9fUiaGRvt}s4X-?Uf$O}=qba7_r;udj(bUB~E05-zZnr9v-E_woG-~Up<r3yy
zoTYv~0!&&)U;vA!7?`)Tn*GT|o!8_~jkg1XjP%AeEqWIrH@tgQBL%<|X<W2v`OU<k
zE~=|r%XO1pA0IZams)7k&q9${%Wf8$yM}Z}KhLzwI55@n7(U34X?b4=qX$IJX^Y5;
z1wmp3Ln7{`B5r-6Yh=7$2pZ5re`*POn5z3In<UqBEgun!Ld<kaK9;8jmdU6Pa+naZ
zui#N#fmKHa<Z8S+ug^vN@meLMv*E666vMS#C@~yNQiWN0w7congXB#o%P~@iJ*-tN
zp{DA3tbGjPa>5fXn_`S6?0GU8Y50$!8~Xt7SPN@CjUlscnnJFJ<ZAhS*i^yW?a#Bi
zE-chi!fK^rr7wAqP4T9%&p#>;j;K5uX1aBPAle<jEwbFNmruBEAp)lq(bwRt79CpT
zMlF6w^Skk3a}NkndXujEKu4M_>G)BpR~-p=%~8)jAt<)Bm>=+H%@d?{;s<E`1FZFB
z>zTq@7u99_PBXo<rLH8cY3Yfq-kP=~O2^kaZvUe9IP-WVcC9A-n(nxj@EwkywamjT
z(rDEtR%UHCTXL(Zx`>UTs`j|KyswfVbQvGAFx(p0SfiUV6ZdY8!xsMKIMyx0@r;$6
zJg24wwPP*DF=x2GlC9O;w7L}um3Zfcw)Y291lK2wUKIH4dqH2=<m6e<di4wxwn^@8
ziR%;MC>}i%raLw>+g*C%DK1}|Ry>S8t?t5vrGTn0as|r;SS^aevTPYAPTv!2q8Z~3
z5zbLQrr~2VNmp8*m!%EspNL%J9e}DGIgKZ{4AxCnEG--}93vtX21ydDtS<>0a&p{)
zWRu&G^D)wSHjmfJ(B8q7ROBznwAWF~Haz2SM_Qwowq+};7f#c2mxp_{nh@A{BNwS!
z3ax|X9h|H}+bA#kM)Wy_se`|;)dh#4pH_%GVN=!JR7-TbO;xu^1%2TJ_!g$}{Nk+(
zlzB6&Fk+t9oiIf$bHzK0&1aK#QDJHjx24(!V(vrE3*6EC=DNcr|2MXXEaF1W4#t6U
zC!gKNP7ihmk3GY+L7fd}HAAwNW2?Iwv99}5>VlbC<Rpwn((B@@*h8LN=ZehDs9O*=
z_&ctlgmMeTWb?dZGi})Au^yjPcYav1S0>OcvJCQmZSiqi@;k1e!hjJX-(_@q)sDdQ
zs=o)?65q#O*4suedES=zXVyvsZ9#t}y(J!-N8TWl)2JH*8^D-LUDi!<#jDVkymfJ^
z2n!zQWIYq=Sv`AGgZ4EZ9GDuko5^rv%RtcWN8YwYY_Ub`l>n53ddrMg&4_VHqu4ER
zikJB%a#5}D+XJTOnn+}erJDN(th>B#M7_njw?!i5^4Z?j#t#SDA`V#h9<)X5W?4rt
zCt6~3??Rg-T_jjj21zXM_afrP!iXJ(B%Y;m(i&2Tn_8r^==?;fYL%4pj(O46rEEiS
z4UntJl>wT220o`s<<YrQwuO05E8%L=nJR{}g`uWnx|-nI+>snWb|p-g0&VSCXbsvb
zsZMY0h7Qfuikht^-87YUOJ{jFT(1JKQe*jGiE=8J=C(^V3MGbIlFT7$co#LZHNMdL
z?R)(i2JZ~fD%+P}RRjjPr~+!<^5>5;gcSy)>~bl(nJhUMQW09Mp8bWMt)63^S5&&K
zBRsDZdiJZEfNB9tk)gF8c80fBZioByf1)9w;YDIlVFbMaSL`g*CqT5dHZ9OvTfyGA
z{y?Lgzc|XisvKO_sMB1UlQB)lhPc`f*T+85C%?RGjD6lMB~-`Q$MoEM)*xf_vO>JB
zjfc2+0*Gq62bpxMUghV0`T3Rn{91k<ke}bk&x7*wko?rk&uaNubBv#dCmKbH;BsqS
z%0TYx6b?QC#ceV+$`WE{6v`l_E-Q+%<*AdJ?7-Hbnv_6H$K4}RMV8O!<SRA#4b$>Z
z&|tsEWZSYMB{+$)8f>e%PJG*H@<Uqshf8he82cvtZA4Y#qaQ;ecL>3GC&=`|hi5vw
zvlaPfCY?c{O0cgmp{$Jez>oV19G?=$7zs8(tPtW9at~H)PX)gqyD#2j+<AZxUA;R-
zdP=yFH*_UeW@X?}lM>WAl5kg@6mIM3!tJ@Ey?sYYP-v>>-Ii<UPH8%KGD4BsHn*{b
zqb^8>%1LlGdc(N9HsoeX`9(=3wYVXg1nPRHasDi~kPVInWVk@yG%QI-dr6wn+50jl
z)vXAO{Cv}Ao240TJi-On&9bX8+WPI=Le%P=(uMRO;`0|0@wabFT*~1|9Bi<n3l4W!
z<zQT64l7*JXJin;7{SQ`9Zc2gow8NZU!>QaUn}SMr_pJ+HRqT#&JIiGw-R)v=SZdJ
zSg%Z~^U&8<RRCWnQk`%YetD8KTx#e7>t^Y-OwS#G4_S+Pw{X;9bUP)RxoEx<O@aIr
z+3F(0ga#ui)}5xR-$~PN<&1Zgh^?j#++(`+esqcq7+;?kF2O2V9?(5*Q~gN=jmj(1
zpGZ3so5~NbOTFQaP;_0;vPAd$s=Gfq>FkyFuI$0?P<}PnI;-a!>Gcb&o)a)}UGPOV
zWGmB`(8Pb2Q8$M|EQoZZ4n8*Ob6U+*E<-;TnPBt0Nq@ps?&JD`Y%uGwJoUTZTAM|G
z@}?`eFf|}9HSz28s%>;9p9k8K|FHz&#!#9nWlcPm&ZAk@psz_!?@o%O<Z^x8$u7v)
z4i%_Qizn&b$%V96VA$mAO&UC})0xx-Pb6Ef>wO8nsh?0c2kN5BU9wGLSW+ln=I5#=
z-`AJCY^$bmbTOcRM~|4k#7mUT1NZ)&o+RS1>PQ;X6Zca@L`iIJr0Em0l{bre6IVka
zSD#fotWekck6gVuq99eT!4U-MH4dv@BZnN$<ZS|E%(I@Ipo(ZFhI52*Zj{268otx$
zE^d_K>gX<R^mP}7(p?n!Ofz3pgCteGR0Z;}%WKYI(w~jAdfrI&Y@-X6_+8-dFxDu2
zokWGiXKB4okeDeMoGW>95Vip5RFU{=RiQ0n7kFnRENI<T`0WQOv99syDf*MMdj5{!
zg@iFuMVA-S3CX^A7B-_>yZhrMwF){rsqkK2tYVP0?2uyJpjWKV%h)c}b6na0({n47
zAa991msaP?!ofTeOO0Z{)>b%}zLAQ>fbC0Fxstb=s_v0!l3z1btq_f>Rm*gpze3%j
zQljd}0PROARIcv#RrgSjegUR)rRr@PyEdVk*1#PuI?&c!4=^5+!Dj)SI_jNN&!-I5
zrEbydBd<u8QqI9csb8&9xlGUXU~OB5YLkx3sMFZ8YE+er1!OAMekzwO;EYs+@blO)
zLue}3$4l6MqY+I_Y^8q5GiuhLW2woXsg`v~l@OX5M$hlBVK1Fj!I}p;jS99eHK;)i
z*Y^1<m@R0JRIo;=Oz?!N4OB2<^H(suoTh@M1|8EYSOYcc<O=3x0O+q^#3mICJX4Xq
zFBNP{rwWFvQNa}ZSYH&TfKj%~*z6;{mK{~KESszvwM@oj{#vHSWJWDZ-k~a4Nx~0Q
zG7#}sGQCkJ`>#9uGst?M8U>ekW&G9*Rfia($!1fhdZgDFsZD-{Z#7FiU1QLzj-EMi
zAI*lbt*|yonyL)fnX7_$ljEBuedwyVmbB3fd)1{yAr7qNAtaef=~irv#ZqN?fedOZ
zlH2MkzBWy1vvLC3y7b_8R4^<1CR-ScOEG%~(uA^E!HAjTx{1f!A5lvMchyixJ+D}l
zEd4GL2yj_EoWN`W?mb9bNlQsPnVPttF*s2~?8U>94^9qTSIVKtn}d;^nBjTLbh{Vi
zNLinj!TYL{<&bo3DBH<IU3)3JpMJc8_UV{;w%`P+IAGzs?82O)MdlQ?Iz(VZ?6xI;
zBs;s!<pZod_QIJ_c7>VZyiy*-@Yd#O<fMHN?J1o$8@!`A$l1oGaT}E?=oMSg3jMa4
zXIn~LZ@EQJ4WjB@L~5Qr%vQRSk~Oha+RlhZJ%h9pjovt0O+muV!ATst&kWj6CKrb*
zqPN7c%8&_RZVTjh{DlikTcZ&CG1eVv-4U3CRYvk#<zL88H^Nbs`=x4U*v{K;tvnc%
z&YFO&COe3z<AUX!L#NU6rWf_m^I^#NJ)>umNOFf6(SIe;KhcR(c63WJm_-h!vCovj
z-Q%U7$wn4uiOyOi=kQX7$yk0s<YEA$U3%&UX}WUd{PZ+$>;M@O$rPz-VM3OMG)&fi
z#t@ze82_td0iv^rj>i&0US)hHdb70u97yA>1QGg{%OR7k{TZ?jlCo3?)P}4A0pFcM
z5s<@~rXgbG30W+lHstS&B7J3#v5mNQhU~zyyFB<D(tu7D3JCD*ObI~sMgO#+cOZBE
z0**$6BoR(O`y0w!M5Ij)!yXDOnIsg5$51sP98a|2y1(~1y2Crr=W`%YlHxd6d+bM;
zC;`EpLsc>}P}h8um=PM{0|tB7+(K!c#nFn6LASB8x^a1Xd&JJxOV!Q&ao+9>bvUHL
z;~=vbt;<=_C5*c{b!MS5FK?J1B8xOg;J;$190m*bzV;jZSLGw0Ek8~@P113~RmX)h
zT@<dIX-NVbLQ{-f@w$f-D((btICvSSveX&E4)nYOLCmwW^=uHcxI(M);<VN{?+b2q
zDDM?-EOd~Yv&cH0EB>S*PUA$HdXQRZAUAA%w<k9y^<(03^b9h@L3B@uIS-vacQfNM
z>hn=Nz3vs^#rc0>_-#Q%jyg8=w^00X26vcu8OWS9#(Nzg?W~30L&lq`^+ROO5G2EM
zOhnw*g~U~Iu%Yog1cU!=Akq<#4#tW>=Ir)q*4tdBF_yqXmZt9zUmU1}7zZHW#<Ts~
zrgZ_XmDWQx6W5WWxQ@)x0j?wO3uD>o6>k-HyhV23mvsEZzmdWH<(}X+ymt$$G*!Qi
zwfC{R)OkXx3JhM;09WAic6^S#wznXW?uj&+?%s+#SolUFTT3X;D0fG$vZ?w$47}%n
z6WPo_I0C#oEp_?lrs{dP$O*4$FGdlkcwSy5GiNGM)@>1~h+ICxEr$ydNC~?)8JOR_
z!&<elFO}15z0KA)qb4I^hIJ#cXf?Kk>#bD<I7yAZzLj=nw|Drj)T!3dJh+>dxHUa!
z8>fN-Ot-%-X|TRz(}SjY_IvB#Om#JTuDBu9xxZB{+~THudP{sBt`ZM07EitNo1{t8
zA+5soGQ+UxOO~Vd(Q*ux86i=r7NR|N_<4}qE5y;o_NsQKAi)eKQ7JS?X`V<Vp=2av
zDEx(@+yrlr^%6`1$?gI#h$J2lT9{y=d(1Gcc!l^C;gEn~s@@=}(FD<YNvxKdl7#Dt
z+Dq%AqP5kfej{o4qi>I0VZ<#P7BqPo0Sj+Ne7vQ7XR93+;ue)KlDn_zxgd(7u<9^t
zc#=g5ftwM5oxEIRdJbxO8+yu66fdUba+jlOXCRol;ytewQUh$>)jnr;Mf*-kNZvKu
z#t_G}EPw@HYFkDI%#g(}&%!N{<r|sq^74dQQmr}`Vp?v;!kf5Es<$k0do5^d<5~_d
z=DsaR1#RDXxhLZvA|BtAak<BaZl|rA+!53y_SQ$*V^<DEf1veVWnK*%@1!jh9#-`O
zhJP7ul4IqcDRyiksAARQSl4Ao3Ab8gSZiiMe$;Lra#lGgKO3R^Y3<v`hr1(c`dE?o
zA^(m1bKxBA(j)D?5YyMB+DqvMB)HA9!<N_p3N}!X1vHDwgF5q^R(H4Z<Evfmu^)gq
zC-5$${L_3fq$Rec<xAI;yu-9YL<M-ZzaTZqN7l)-Xf40PzCCu;Ig;;|dJIykrsZ$=
zayE#ZsZgiO+Xxx9%Sc>Uz-=n5?PFyLmGx>=qf&*noPx%<^vHLT&F$Zx%^7rIKbp<M
z;3@omIY^&2t8cRj(j}`CC97MoSEV(XBDZc7QmC;QZJw{7hMkldS-4d4A7w%z$`A*M
zT*Y;?x=s!)chq#L<&MN%QqLVyzpo;GPvi6QKKK1{c5d%sUf=T<jf@N0W5=E?<=iGY
zssuTa_2aLiY5997=15_MR1dNwqQ)=iXa>?a_$7@%d+c9{f`X3-awVkMk`FC;u{Eqc
zcJ~k|PK>5IcFDTu2|c&84_4OOmW2v6HsBypsNO|!RjOxuy627d*k2k^GH*#6^-jwj
zcx;cItD<aKCegj(4PHVFi;vJZ)rG8`->FZqxFW2T;}gy>RS(0}`@mwUj{Tvu_i40M
zX00U+`@|E{f38T7zEBoMKm3D?0Uk)G5%bb*(s`b|Fe?44epXxc?Y?eS`goqJ$>8y<
z{J+Sf@BO`(lMDyA$9T_DNlQzBjFJ}N=TYs+ADC9GMwdLGwSrZus(aA$CJcS2beb7;
z6AoZq_1A%Evky(X!V~<h>7|UMu&NIO+=<?=7SWoF@xB7k+ZT0Lztia9!-c9pZk+>p
z?ukLTj6`tAmV`{57$!_yk-*^%W-3SxiS<_b<MFOiF*8mPy3z<T1UXl^lic-wZ(Wmf
z>dDC{gpr<$T^)uZexj+f?$9hw$R)!PH5$r4Qq}&QyO%fAAFGh&FA#z8QO%P=m<jvX
zVK-H+QH1$`3x8>fFhe$DUG*`9d1o41rr$uAI7OHt-seHYpor>PI+0`#`@te0W&yW6
zmPL!a9fBURA;rp-h*hgesLy!v@&w^wcR2Dd1`FfLH3G&5vED_*&86R~{Yg~4(oVql
ziHl9f!QKge2fbVCl=f6TZJ|%DBF*(Ta1+EoRux%1JV+<!&Bj3YTtS5%9(g=11oY(x
z+^=D@!ICnI`&_J3*scXfs_z)_-m5)!#voMzMf&y^1Z_pc5m$MUJsInnOQamx6#+0v
z;Ypjlds<~dSl9`v<gB!^DFb5qb+Vtz-vhiil7`}M>q&U3Qq&pz5h=$3;Uun~J3fiQ
zzjc2<gP-q>AwD?n-~xa4S^4WUdiQF$q)Bn!1i}8$<0KC6>F02HkD1FUt$n=p{+PVa
zqOIjLzv6MTD)ybN=XoDg*4}x3k6oF(j-7l-^0Zv8pL=f)Ie(V05^_x73~%e5gsM&9
zRnP`k6q1F)cBUkVLu)S#yl0nU#)58*X%e19kPuSQ5b`6XA!iUhoG+Qi6s(9A$M?pY
zaZiV79FlW5CZEP}jSn+DUhj9=@*KwJuHejCH#Z&*xzF=Hrm!wxnAO3L#@uHUM+rC|
zpQg36&<DwDQgVedaN#TbCM?-*y=|Dx6O*`YTlWhNop02oho2$*mn34n)$JqiOYA==
zf2}>!b&=)bh757Ul!TG#Fw1R;GD>~Pqc1X8Do<SC4yoD`*vgpgM4~%XcPDvMO}6xf
zRmZvJCa)<88m2oY>bSXw;ycO38ErOdwAL||$rY}s%H(Nc!|VVt_ts62Ra4hMqup`h
z+uc)q@kqxsH(1Q3_uLwo=~-zZ#!>qyN$a=Y&<zT@Y|92;Zavfx%sjyK(rZ;MNv&sC
zziklFJFfHVQXdk_@$vJ5kgZ$QxSPGE@;+62!mP<hoP*pPc%R$9YEQ7-Fgb(QS1gBi
zgt_A}rJGXU=gG`#t)>mfgN_(vxbsCiuqF5jb`Rh;z&*~hqpCU36}Ge;>?`L%GWR)%
zAsX!ce4a2r6<QO2T=HP*8D+U`M?&DC1O3{+{UGRsD(dvw8R8+(75ME3sx<Z64i@8;
zLmKci{VZV_Lvf2cBU(f5w|++?OMjqf_E7GLB=JZQ_eDPTUy!1?9)s{z&n^TU$WQ^E
z8yiwpz_h$OBY`#7LUgX>c&|Jm^#d6`@^Z(d@Rsdl)Gxd1Z10(5r)$G#FybiYu&Ofm
z)E`~kY?lIRkA3}2X$W;$UNWzjy`E^_ycVo1R++XQ%<z2a9aE*IeKewD2RLq`wOQT-
z;Xv=}kusyZN@7yikWAGpC{!B6mvK-{=uHFA$f&1W9B4T|VXTga`;~`1EN~1Y!uHs7
z@rUzv-Fc?pIZQd9XE;BqI}i3df9a6W5r*@vIP*psv9@3@t-@KP_1*}H8(DXsFg%e&
zawV49kQebIPXUBHBO0y^hdhCXb)oeVn5)wHJYwMbg@l+SAv{sP6bCNMj8f?|i!40^
zTr{}Gwf|WFBK%gUbsnpF7+uw6S)yPi?#h1<jkWy^e04iSrx4%{HNEh8Z0jY&Iz%P+
zx@)BOouwp$m!UigK{n8xiF=gc-qZUh!=2L|@@Ask(~tU~jD~QH;Sg=}yp}10yFV)*
z>Jkv$k3;sODkyD>&UbW>!golOGjsZAaTG_y-F-YE8}p#U2v5jUz}l$C#WdKv)dfyn
z`g?=54wS22UvUvjZ0kZ0bry2QFIb@B={#vkyq6-6&wG<>hLe}@=b1Ze-cpQ*LcX4%
zX@RaAgknwDw#ROeB^2hpNvvsZTqPbq{jCtaIzi%<BYV^<8G0u%=1yY8$f73HGR~F=
z#4r>-GGZ~e$6kb1zxr9t?yrc5P-6lgpX)*hJt1XN2rLUWNKUm@nQ0hvgXJfTdm{&=
z4`|su*+R#^&s1%LhpoDdHhC}mI<`zB6J+x=B`h`Q9rjH<5uTJ_c4WGH_S))tGvJpE
z2G)^n5&Mu(%z=>J-BUTa;dxnKkR}kDe71<cc-Ur)XksZgd{jeiFI#PPu&wqwc0{(w
zQZG9qEZ*2^gCOBqa%qRh9>s+Tv$(ugn-a`&SvNNE18P&kK!DkO0=Lr}Tg<XK#CEyF
zvRnM}?D!SItPls=0%nKNPO%ov^7!rmf@O!v;;*M6HK>6VX9ODWB}F#DYO}*qX>$l?
zdMQ)0)^R*2GJ$uoSyfhBHE-4ir4l17ZdHgic10`{jKM2C=<})_Oy;*RYCxo<<{l2Q
z$fsuu@{>P`mV-*D#t)+-nvmEf6U3CT!l1*DqBepxGuK`ul7^X_7a@O*_oSOxBKI`b
z2FaTB!GRInl<*FGUiNt)2BlFLbcBOC5eQ&zHW5$x%Z0T!bN5|De=!G{@tE+Hx<AZD
z65MOH&X6JFNn^$%j6O%hcrsRWT}#{WSPASTV~MJEmeVZN8#khNhbJF#4>)AW4RH1K
zhTvT-rOHj=!@-2*{LPuf^O@*n_?sW^8~(<``G&u^n{m&O+h<%-I>L$`qwl)di%E}?
zd^wYW_@o`S_%K;Wi)29Nyh$Hx%LTuVp{4LPg8E$CaFaDrnK$V(0b{n*pHONv`L)A0
z?4y%b&(G<D$$QC8@_-j-%V6?0^lC8qaeCu%W=j`5j<tWbWc!o@eg5gvR^nqc`G7y#
zu0y-uBV2=|TJylYkeo7IA_jfF6oK6>a0J819^PyHQRu_R5Am#~NV$3vWBu-3lbE6>
zA>_!FDN+%Inq-|}z5WK{zND-`Gir1VLKEidkKC_lZ|SW(;gTQs?J)?`AcI22h%k%r
zgNzNUK9hCzE3beOdh3vdJcjEajGT(GxC&`{ORmRJgmp%GXQ(2Mny%X*+VOcIp=vf|
z#%+_;HjBQL*dFWZD{Np|UW=cq3BM&$)?sQe@ctJK8}jkoi>ij)DT%emPQ<fB<X>lG
zX@R94>0B(QtTM_7qCNIiA_2YEh(Mk}b20lUNHDAAKZQsd4O4sU`?SVXtX{J5ZE20!
z88QI>v~XJM=iDon7}(5^`f|Zq=>fJCv4ZIvC+L@{p;4AdnQZetqWh++CsHO|QI;|1
zxd$rYl7%8`(kPdbj`?dAkGx1*FXHSUO_NTWIg&__L{_fIWi<V<8{2^*m$A!;N-f5=
zK56=+Nhq4+jbd$_g~RFxz*`VbvUzG{D9x$bfW=AH<S!Q{a$1UI-{kk$7eJoH3$jii
zeT8HOTCL;ssS239-Q6=Sf2jmcW7BM?WlUKBcPf>ILc~-(nn9QN^$q`824mq}gS05)
zNu5*il{$7p7<{{4RyrPx2g1Nbp#k-i6fT~$VD@D|hx{xLAm-M!^jS<STB>EH<)^*u
zcbMtA%afx_MF@nQt%S{9&<#C;0j2S1Y!6XSdwOgqsAn<>zYH0)aqTYNQ2HAq$^iGd
z^cZnfEdj1b=;ZFFL^8BSKF@|(J0krL0c42yhN2CTq*X-*QAwEUJzL^yJ-jcYrN1PH
zdNafjgNdI^b3stau#NRTs{8RS_6KX70qP@?qjH$Xm7klI&kQRnL(S>7RDEQ~vfan-
zLU7|DTQrz+tS&ej>D1R7F^vYEIvi2U!0EHa33Oys>z~_oe&<#w2emRhzIJV2A=OP^
z?6|_?`c%JNU$t;lq~;z~H>JDxymfMgU76*I>?q^u(u=pW%d@Ea1|My=jf&KVI_;0L
z$I$MIzQU97sSIS|qgh{zkrvD#j|f0vq0J%^rHx)k`W!`p%fW-2gk2~=EYUo*F(ij*
zK%GDZY&7sQltoR}z)2>m@*HNDqjtZ5$zs#1{}9$*8Q$)>MnY{%Q*GH$+JhIB1?@qk
zG+M|wkKNxBFP^9ePH}ia9I8Z4L;H{&(KJItG;nAi63DNNq~z<6w*_uU0Pme3d#PcW
zqu$A&YQ|+GHf5S7?YC!m`VS!nq#x}s?^DPb2CXf#?$=ryC-rs&iLJYhM^qA|1(3Ek
z8k$)2uFG@K+w)o}QUv>Yn)FS|6Vt_FThffJ%9A;b1wjuFNbL25dH=%h6mI5DZqLio
zueaclQyn73;fn8ZP$5S89rV2FC`oE+Wbf_iclV=F^<pJa@{+7NQtxfk8%>Zg@?)Sn
zYWGsPi{4<myV1j6SA3=Y^*-Yd>yJGxKa&VJR~CDjVwK)6d%se&k?a~c0{s4UYR&$h
zh&)k?GNfN=XI-aD>fVQCn$tl+$bPVDkwa7B5(esVb)h_x3YLzchiYIqXsa%+z(;=x
zjZ`R$_seM~m6_Nh?$jHoPicJ->egA_*5fDnRy0?0i3cC{At!YHp|4rJ5zA!6fWd)6
zR!!?;zyt%1H(-tdiwwBXfU6AnM+3fW!1oP!*np9;l))Egz(EEaW<ZMpvkaJPz)}NN
z7_i2Gs|>i-fX^84Wdk-Fu+4zS4Hzs>s|p?lJkNk*40yQ#ryH=yfC~(GmjTxqaEk%o
zHsCh~>=B};lVHG+2DBJ(x&d!AV5I?nWx(|Ye93@K27K3m2Mu`0fT5v!dczEOi2<_=
zSYW`p23%&ql?JRg;2#aR!+?J_pd#82{CJ1Tfh$dGnxsR^3LSP068*Yv|LVEl@9y(o
zSX^3gLw-@7bDY^V$6+oln`b^}NclO!<?8F?KC8^7+|K7WUwnus@hl$mCnQx2Ng7jO
zMn7}HkV1iZ6NVHBl&`=&$8kfs%jwQ{jWb_2q}-h6GV38`n8n@9Hza9f!8m0*vciYJ
zN#U>*R3}LKW>=Zp;jrt5aIIokKGq$Gi&>9fkEvpqU?u(pD_`uIWqz64Sx)+Mic9T+
zhyDdy3d(NC&nqdJnU_C%oY`r2xt*oOrL)XKN{p}zdl_`i>jHgI7|@=Wl$3;is8*`E
zdElT#J6E|3Ep?ZapbeFO3N%^^3e`dbqk~gZQ$ystFiFc2pF_=KvZi$l(=JX*x+bfe
z5K2}-wXocxTt416a#Zkz;X~`Dg@pma_!Fc00s@1ALqfZSbq|k-jOt;Ej_KK}cWj@&
zaq(yL>p$Skf#$OY4Ne$x_Blh(JumV63x*9(8ZmOz=nF5pc+A*w$>S$nGSOn4lwwQ0
z^s=<{%dg1DoIEA#%Bk5o966bG?ey!epYe+ua`R^97uXAD6&2q&yJSvjnd2sBxywCw
zUd8+cH!obYc!`09rlpiQQ!9#HS<bS2dpQK3qm^s<TAAk5?EDSW3KVTLP5Pq<e<)33
zHLZd9jQ?Y5c#^pevoEjW>Gm$>JGz)xb}`@C#e7#6^Dn!YLn|w9sa#q~fd$=CdCRiO
z-XS5B*z)DeK|Cp`GOMx%>JL3<Ox87(lm~^Dl~n^;=Ao4}m4wnLwxXh<u&{0w4#zx)
z<COBk%YXD|*1G-;rS9l|U0uG<oJLLhp}%VF)W4JcFV#B!0<@p@*Exn|TE}0Y_S61+
z;m!ZiWv^%c)KV?_pXPvorT#zP3t&G6eI+PxSwP2MV8BoN^MyY(_y1L!AFBb9Qg8lz
zDT=8>A8ovw_+$C?xp(#d({kJ4D_ZN&>$(7afMwK#%B9Pys+Zq#YfbHKo)vYs-?8$}
zyMB51J@?+X>i%E-`hnj(_)z`oH4m?S<k830{r2%E*8lFw4NpD&`#(JM>>r=o`1}ih
z+VtW}n;ROpY~8kf$Ie~5Uw-A)*Y>>Lw0GbBH{Sg7TL=E~_B-#s_x=aXAAa=lC!hZH
zZ{C)Jt)G4V#oyb${Oap({&DEr!$*!DJI-o}_Rn^pr|%$tQV06)&i}tV{ePPNKQ@3l
zy}KH~{JZm?mNstAoN+Q@(!T<}^UaxjX3@;&Qx2J#!wU+A>xQgM79COY+3flDIWz4}
z-K1%g%jTYBo|5k>6X$HZ!{u|Zx@Wn|U7W9Sm#D}uck5$gtHW8$PJot~=gcoMBD~Z-
z)9KE0>PTRBd0we9lCGqs5x>N(5vRn5Dkc1UjkqKpjqnmi%g$qnU4R4MrOskQr)fDw
zjL-chO}oZkP-^dFk>l1)nPsKQSGL=Lc`k`Z!b=zpe;R%?+!f|dcd4s*j@@i`I?J49
zO^Y(71UVT~va@wtWtE*i`La$%%{C>|nm)P1X6i*rqee%CTT9J(4o69Gex9qitkhhT
zS8kq@S70~iVef*l4j1zkb4giVf!S4LH>a3=>6aAGbV5FJacO>;(`nClmCPR&o>gMc
zE4Q2T%Sv5&`Gh1yr`XRaH<vT@DRbgt&zoZ|Bm;BGoOa?sJ4azK%$Fa*Z&XzH1!ijp
z8gAmw%udfB0Z=S-mdzoFVy0x}<*-1>d~<=@DU+R2qM9pc;H$W_*j1cYQoKM#AD$!r
znL0{_?SwSXbkD+Umg!VyT!)#{U1q$_DJyrGONwXPiCwbew3oX}T;{Suv&^z2F(@TC
zU65Zk$5C8jFE9@so?qfT*Iei>%~v#4c;<B=RjSV>$vpqc(N<EDnO9t@@-F!vDfupC
z)@m;;bI&R=mpk(E$uHhZ%1HJkf_0|Xh%WT<=iROs-qakO-mW5$E-THq5Bur#=$uZH
zq?1Byf@4P_1>y(%M~)G9cWK^CP=$Lse3*;uc@8}$@pthL<a1ter+}*LI>KFa+HmEr
zf*%NXp@eg|;kdcQPM15cq@$3eG*tqE7xm&a^uM93)Xr>hILreuyCjQ#yhe<ba2@$B
zbJ$CzE|ix+hXVWD;(WueRAkZ_VbIB5;h_G&IYOO|8mg+h@~7xTTjujO2No=L6*=wH
zN;qP6=P(lQ>FHwxD#&x?>1gYT@EfJGLZ|Ag8Uv^OCK@V1PPl)n(fClPF1wSZ2k2mi
z4pbmG%3bO%7oyI~`)_Ot$WM}@>-W|NdnqMZRyxOC>N4^p{uN!n*MFXKmRmfR`*Sb;
zRedX@k#k9fc9a#Dy8JDbL?g|gU2!*kNO8With}tyWxl#t<u)ZT(NC8Qy-^gRhEo@Y
z4I8G7cR0&tIce=m^Jul*rL$S7D!qjAH%OT(?f6;Y;VdwSw{d2|ju?F9Wb0&s>60&2
z=Jd%n1+$esTCILqK&1>gEyHz4|3EiEZ$YO)-$55b&xAXD6kQcP79AJ;7u^`W8J!w^
z8(kbdopgA7m)U)59M{l1md(p{sY)mISC!kHQ)b=>kEVAt)K&?^hkHg|xywphH`kt3
z=5Raw_PU)OotDY!N!~2`q_PS<<W<?JQ%8*)X3Jn9UA~kllc!vjlb{=Z;5VRmnAW=h
zmD5e@JvvnDJu=!65FV_Bj}F(uouQ7H_#iEQW~`$(i&x`W;S(DDt(T?^W*@HMbv<I`
zzaT~n-xuoW9vh~`y27>Cg6>-EX!KKK8hqj8fWZOOr-XYK7%(7G8{mr31{6eV19D8-
zfYCj)0e8i>^=*o6i0>b&MFqrYp$)-~pxnTuCI%cr3KeD>VO(9pG{-gt#D{C~E|V5t
z&_j#QiPGXnM{4nR5m$VO7XFbhCe}=eE0?(92ZU-pzUtNx;t0+S%IcH`Ys$ehNlV}|
zpgB@AlRtA#v}OiJv$KEO8O?D`eHwZ@0zw0|(2;>j0nwpaw5yvI4Gp75Mm7X=57fGk
z3`q)z3)AADZyfZE!!2%PZ%6#O5nA8T1zO*L=~{GKkLJjx@P;r)x7^Sy9k*S9q}e@4
z>mIO43xw`^8HH0u-6<o=YHGA2KB1e|v)~!6=jcCZJp-Q7A|Q^U5$jJes{FcX;UhyG
zKH5*6plMH_0-DG;U;Mx@aAm&d>_}b0kHIZQ=(sHcS^_D@c+!lY8r$THs}YvFc~VDQ
zF$N8M?pILB@=#|OY3cZc`tc!q+Mvrc?E=&&!_Or2#i(pwm|nqJuhHGKUL#E^4-#fa
znx=h&@`dT1PJKoB!o*(?l{(PXTkBWQ3;OoddZqOEeRx|~b7)g=LtvIppJ~JsU<%bt
zl&6XOoAyOGbTfK*(DZxEijT-Q<rYu5#ZzwaBV!u^Ou>X9?8pd54Dv(z7nrpE@I!xR
zTw9;!-c3ClqW$zvzKSvT)tXjf<fpqiN;7YZ*UYXsc&RUZ)JHQ1^wi*XIJcv2jhB5-
zl+?3Nt_7+(5<wjar;c=|j)Z9gM#eWw9ntZQ0H<)xG}VVUd|v?H=TLsw$2;*C7NCVm
zc`3dKQ{|xe)(PK=9h<pQcjNm9Yf+<nYf)c?I)oQ0gjQ0vQ}HKt!54=sPz&L))c7-k
zwTQ2})X#2#TDO2-b2C);@8gN*Zql@asFmbZV2sokcq^LxL{E+Mw-F|0D7T`XHt1&5
zuPmJ>$(M_KK@0e?tygo5;z{9+SC|>a&_KUzgu4s#Fw94N@u+r*_Nbs6?NX=~J2Ivr
z=2SaBkN27jU!i*KC2~HUb~+CS^bOPcf_vW_AUxW4WG_cR&rs@OwAS<YJseTFky-I0
zqAncliq;0gBmLl!zN30Nd$dJ1hc|^a`0BaTHN6bsJNzi#3lEg?Nebu@sPz~bo)piG
zJZX!hJci;w{+x)^_>|tXj8Sb7&E1=f)+@=!-wuDA-Tb_YmEM;11WKOYh|p9U4ee>4
zn-y(4*Y%OH&ApmB+U-YIXxc0m*oPam=vubV<Mtv-cvfIc-*D&?4Q)(XUuUnjm}XN`
zR6~TnZmeK2e&9;_sLt_`M<1`$<F)~H1MUJ(;&Uf_-kUbic~Z-n6rU*kZr0)h`e;4d
zqMLg(MK**xy61*v>9nf{H{H*`AM_It8K^}<U4LDfN*}1|eRoyId^jdQ!x;zEQX>!X
z!>OaAZweX^P#AO)W=8sQ*(j!8IBio8_#sN`H??n@PG!A)6WTd8Y1(Sk{YIQIF`-%v
zeOSy?p<Z~dFYT%qxqpp%%J65@(X1bff9hsVSD}3IpQiuS+m=4zS|8fOKJaB9XV2#7
zrXCHEj)>d<RllFr;?D}xdeR>Cgok>Lgxa_Xk4BS^7*#)_DE~;U?^NNWjyyiJThq3o
ze7GzA-lCTgq%!)t9$Ihu@7{#(eHY^qX|HLA{cW%6pJ<<5w9nLMqkZ<*-6?xCtqir(
zpwBu^j`_Y%WPi2UXF3)ByiYHjsA)g%)9ZBjsr&R#1~76@akF$&>dH}5$@Bt7Cjpn1
zlxN#rSLc<m?&MH@%I3_;D=o-ipV_M28#L8ba#iU(rU<DO+S^)cDf7S-Crd0$ptG4F
zu!w}b%)ktL-dy`B_9KFGe6vRXe(K|$@bFnq3cjk8C5i%8Q&KDPS>PkqON&cLiZ(GA
z^iJ#iN?>}q&CZ(6EW0y{wHh*~-6uF-txx!M)alj5E~Bh$w%c*3u}(u)WHqo>TvGBJ
ztm@fQSjVzgxU}mPj#)DM(XvHvO`+=d3Pd+0HB<C&k}fnWE=Xa`DT{fI_Gf4#3s6}y
zn*{NVvZC3^JW(i31UjWJ5!0nkyIpGwB7ZWYQWHZ>`>Uka$vi=PT1%MrYuY=387Y~0
zj%=5#dRcj?Iry650(%N44RXpdWsP9ce3xD89pu;Nl=(bp?{yB#_-%Dy8mkWq1#L)h
zc8Q&}&m)p{W?6x|#Ga;#1Ak`8wG@=Kpa23hY6%JGyg~k%;II2mDPxYyQA`Pu?JCeM
znNdls6sJ9BzQeAK)m`&gk8ucrt;qAV*-PxMQ`qO54s0a!WaiW4`HBF+IkjUQK&M8z
zRcjFcr#fgErwMV5w&nXnkn2Yjb;wz#8L*~3q-;}Ihk?vmy)xNYEpe93*Cq#D>9#xP
zXW5-<ZIi_|MGiQjP;#78oIl&3&l8fWQ4@_CKvkTg=rW(BmpM7C_gc#p#n5RJbc#ut
z3k9Kp<zyT1^-7!>YOzo!s`eX&oz6IGm42#SH{BV04Heif@pDfqgS8H08H1Rg4NUi~
zpLQ(|YiU8YqqtPhM77F;zSJf4;oeSW7zpZ2f^XgBMUu)ScVVGj4zGM7ydpNfN}@fg
zFv~7pK!_AArKGIf;5_XX9ZRaDET>tuUv)}hireLIyCmI}C;5U9(pq%lz4@A6T9T+$
zyCQY!<kSpSAqq+u37q;3+WHVj*EQ|&ZnB%s8kwPnV!j@=64k~SRb(}^MQd6mDi_rd
zLzjJafM!OYgtDNrP~tZl_#ELlm#Z}a-$i**U!jhn%-Elg8jrdRbu}s<r60Em)Pl5N
z&YEyy2C)s{T7(v<S+mk_U@hCFaxpRghI03u8>G#l2`sl*uC=D6rCFwHoz4YyKGUT6
z&q-;l{i_328qNKz68jD1#d912)Y&I(VyQ13i)B=rRg+W-%G|7fmUq_Q;ItPivszBm
zopi0=#fO{n<})Z)GWqlOzk~wrRh%tH`Mw7n`gyVcE@-(}U$^wd?=zpYi%wnnu}|jG
zQagU?C;mnK{QXRUpDFNvPl32k^!6akfKmthpnUZ!$j}D^<4`Q~s{WI6qe|dVH((?x
z%z)huDBIcMCTA&qZW6Eby#h@rNkf_jv7@Wi=vI{y`?FADe<4cDR>PcPn6rQqW~yPI
zZ9v8fDt?wQRoXHjka*^x%qRz{Kgx*`TqPfZPbErlUTVN)Kyj}^iF-9l;<*!bF6u$U
zyc#I@twl**A47@1=TL$l%K^&$Eugr^K@_2vk7gs+d~m`2iJJD>4D-H19-P7HU-(6z
z_R|wJpZ5C~BK1EQ_2~~o=}4UZFwXxVlK<kQPRjyDFMV1TF#n4Y`}aiu|2RuL6|0ZG
z0s@1jnbp?PVCOEIzw9i7nvZ^<YgRv^!=(>39~YfvaixOm@Zb3G+Yg&{=Tm-{ey3Ym
z4EXF%^lvr%{}KPMulZ!n8QQ07ylc2s+vW4ezj(C@aU~thm2dyzZL@a6+c&;FvWsup
z=luuXZ$84F`eHrg=oY>I;##O`J5#!Z2<T$|R~g&RIC&i0HJyLAyU^i>XwhW;e*BaE
zrqj2fRfm?(b(l5K@ZZniKVOCovyU$+7F8~*uGYheS-wi?Z2ucSX}n-HHRh-Xc8$Jk
z-n*I!a?;n;y{q{o&ltM8|Css5!vC22KO6slHGEfm{!`38{vT<yGb{hD^YID;))=tb
zfRzSZXut{sIt*B3z+3}n8PH<D(FPo9zyt%D4cOm+aR%&dz-R+T8ZgX&!3NX}c>D_;
z|HB4sGhnj;-!R~-2K2?h%`k5=;4=nXXTW*`t~6k!0V@pXGGLJbvkYi4AYztJszbi^
zWmp$RYcSfWghajF`Dfu0<MXwDQZFP;U;U7=y?owpbh@cd7V}2KEOP|;Y7Dcl-D&$;
z_iqfUw2g*Y<^=N97-pIC$d_xFd+A0k$uP^DOTNQj>G8$uMy<&(BiKiMs|+*Sz3R&~
z%re)JZ;W9+Q#WdHhIyc2e(Fm-ezRe&FwAEe=E^qReUM>pHu$N+FgF=ywqDfNV3-#e
z=BIr8XPDO+X4N@hx5_ZHEUE=??OEo1GGDTw+G*G;fe3bL7kWq;m{Chml}zZQtlGZR
z`<bll98CZBUzY8k3*R<K=gXwQI+VVyGd7*g(qH+%`ap|czbm9ee>BXmw>%K(*Jo`t
z`Sl6k^z`W~?_Jf$r#EkUDPGqHZ{FSS_R*qW{rRhV`fb@i*<x;c@L5OVy5DX8O|hkE
z#)%=Ho^kt>_|_`RP4~WaPfCxFx^p)?XgRXE-uC&@o_8!=_Pk~D_%|PYy*+(k#g_e+
zvK`GUS}J#6_QEgMSvM`8ebqT*>%Mg~FPyaLz1!bE@|$C=iyyx-W%Xa@e*EfJ=MJx4
zdbVw7bl=AhKN<b;_H9RPt&hF&^|!4bUcTU-*Hi7U?!2?dqfgeyfBf*JQTD!(?xnZ5
z=k89+oHpr`$9_3B`NECA|2#YMu}^1A*ghlK^Wa_6+h;u5w%Xi~^T>*e^Y)(bO!piZ
zGNbm$JF_0Y=kV9(Y+kc##(R~e8M}XdpZT`Hskz&RxXG{f+N-Y_A_0y~ylF!CTMs+r
z=kUbo1<4;wsk^VVXVpI@Zry*rJ^rI<eV^O=<-{h_;OfizUABJvV_!_PJo?Atk_{m*
zUVKaI#8DGAO<M5jn|E*i^WP?JIdNi7UUkg8SD*M~;_!^?KFr+q(%tv`b@#-(wq+-~
zZLjry=~o*jzCY`QyT_*f?#!oOzk6cB;2j@rdLem4o@c?tysNHlT>NzQ!k&M+Vd7g~
z46h4)>8|Cm$7~Z5CO*<K_K|ZAE?IZp#6{~@f3m4y;iXOQU3E$R&7rRj&Y4%$e&^B&
zcOD%VzaW1|%7}*b<Ik$yJ7(Es_ifZpyp{ZJ&9tz7PkTSU<<X$z9o4Cmy8ZEf_r>oF
z8#n5v{`&^MGxCe{mD9&Qdh1IK*S!76vPaiEJMyEV-^V;Q^&#7}&qbd<B>j^ME*d>0
z`^i1Chum>(@Y;s=w=6p5-EroFf2)~(&7I>nXH^Y~n|y_R=8391HiX{2DCUz3-hXJ%
zzFooZJ$ir>L)1+^X;YF>(^1kM+=qG=^#<x|R16g~2_+JU=SXGc^MxCSUe;>nq3%UJ
zgW8Y!3Kfmt;iybhi4ji5`SST7-hTdmfC80tKz~Cu9Mku<o}&X=bx7aadYaB>z373T
zq7Hn^Iu{+##NPC8*iQon#On6JKzAR`&thKztVcB*)#1B+bw2{Xp@H_|N8kuLs}g3J
zqk(@wt;GK`z$?$t^(DY3Q5&(}1spg)(|Uu08F)TSm4sg4RdhOO=%)euC2*G?eScu!
z5KUW%J{XvGwx->UUf_GE_2`>{!RL^s_yLYX2_57-(|bcTZ4>s$GtgdUK~M6ItOD(8
zl;rChVD@>seGYJ`p|1wMjS@fa0)tq)6MZo7O;j`S8~{e0553Vx1Fu0z{L_HHMIA=J
z9(djbdRd$gj2Xk4;9>Fww2me3=xxB=sPX7~kAsdVNlRdkp%?fol*Io4a2OR)$~Otv
zYXbX~5*FBmDnTzW_Y$4{0^hQr$Nm5inGV`|@dG@JlC%UmZF)IAlS-d_sh(COa4G6t
z{I3P>Mv4Ddfr~HGwBy)U0)x}Ahvou@q6ANYGt$BF2)F<rM2USp@T|*qeF89V3T2I-
z0^m{93iQW;)+`-=8_;9uR{-z15*pxV74S{eP<ZbE&^A@4iNKwx_4wHZ%*@vHS-?do
z!J!iPyrJI&+-K-N0}jmL3>jg~z-v*Guj_#kSLyml;JsHvKm0rc?01bGXMbS#=~Pna
z6A7G$lCTxP$F9@McO7uv4902rsQ{M#f-*+$01nE92Iv!j*P~Rrz`G5-z-H7!{0RI`
z?9m73f&WZB?{5IVM2Y=3z{m2b>*$++lM8fuW&s=Q_{UzL7bX4$9xSAs(SHW~VwSEy
zJe#xAC3^jpo%h#KLPI%^_c=<!wgGp~;oRK`cmuem6xw6I7FbY5AA!EX!5IRS7yVN=
zfhVdB{Wrk1PU;Y}5;&k-=R-4a7E0180$%T8oQR(y;8&<h^xpvIx%IrS1Xj$2Uf2uV
zgc2GGOq>S~5YPF*nTEaq_+<t7N<6^eo1rUufpIADZwB7B2t2W00gPRY8~hdr46KB=
z(FX%FP{M}-KSYWBC%`#Nb-Fo#smpZz#%g$JIXr-$NZ_5f(w?Ee8+dt*p7$(ZJ4)!O
z)zVj@q>X(8c*MiJ0{wB|#1%UIk<X$nLkX>_fwgti5&WzGK8%twS_|BXdKLR!z)uYO
z=-a8|D=BmA9{}z}^(WnTfj#cj<BSG+P~)+$2R?isc}2e#_}FiB{W{?4N2%*#4~+Od
zxS)>&Ui}A6TZeuc@I#d3>l5JgXDA=^*8^Yp6ZA*F3HbRY==vRW2L`=FTZldwct1+Y
z^a0@h&F~iXZvf9}(D57!e0&SE#C|>SU6hog7dULIu1^9cYzGJY2y~&ukHFX+&<6WB
z;6=OOar9$=-=HL2fsrpmE9?cPpoHc&;Ivl=$1FhL?pNUl^ltzwUxRMw1qScY(-QbN
zDntALO|R?y7xHwpD^OBi4&X~DS;3XNFrT8XCtZPZ&teSt2$Xveq8BK47ep^G!_dq9
z1-U06_5yD=^m0~S&cTblKsnnkdVy_*Ue3468FjH2C}*@qFHp``i(a6dr54--%9&-c
z7bs_e#a^JC$rZgoIXf$Qfz2rK|MU0HQy^GH5uo;P<6s?Mj6VB7ERw#*Ue;yOaGRDJ
zpiK{;Zt4NF@&3!Y6>~~T%O?y%K+(AJ{383Dyz&d?_%7GUZQ5~p<#UG39WjUt$)&}G
z9B{gt15KO+oiJ#`u%tnkM1`Bp<2jpDuFm9{e_Cv#^l*eMx94+N*fn3pBU@MF{Z}2c
zoW*lFA2!Qg?sx3$oLWIpIg*-TpKC8Mm&osgL3!orrE|+>+ns~V?qX|xK1U-b3@Xek
zDYp;0Wc+Y{+$RV2$KT1vDXEVieiE+Zhx;>4@bSZa^t>d?nq{@wxb{75nxXk;%vv*T
z59OD&X4;zEH5F?r*Bp4b`C;$FS{v;Y_VtgfdqgH$beCFmeO$e{erSDC{g`@7eOi51
z{j~brdPlu^?a;N&ziocJ=!u#q);+Q73GWj_*IU-7t<PFNZGG-~$NGx(HR~-K(l%sm
zn6@EzL(vAuhKdc98)`PJ+^}jx{f2cLp4zZ+L&Jt$8=5v8*wDPeyP<8v;SF3u(iW1Y
zRv%XX{pl8waz%Y*eNFw!`c?Jy^&9J(>JQX6*L&;R>JQgztHV}DuZ~+ibamS5X{(D?
zSFEmCy=wKk)f-puT76)(clF`bVQb>n3|%v3O&U2bBIh-0R;^jL#_@2)!;<XJ-_I2I
IPoTj60ZRh!$N&HU

literal 0
HcmV?d00001

diff --git a/Test.pm b/Test.pm
index 2365ac8..5f72479 100755
--- a/Test.pm
+++ b/Test.pm
@@ -7,6 +7,12 @@
 
 package Win32::API::Test;
 
+sub is_perl_64bit () {
+    use Config;
+    return 1 if $Config{archname} =~ /x64/;
+}
+
+
 sub compiler_name () {
 	use Config;
 	my $cc = $Config{ccname};
diff --git a/api-test/API_test.sln b/api-test/API_test.sln
index f21116c..d2e0022 100755
--- a/api-test/API_test.sln
+++ b/api-test/API_test.sln
@@ -1,18 +1,24 @@
 
 Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual C++ Express 2008
+# Visual Studio 2008
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "API_test", "API_test.vcproj", "{DB35FD31-F92D-4A13-A382-0CD3C6A78F5B}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
+		Debug|x64 = Debug|x64
 		Release|Win32 = Release|Win32
+		Release|x64 = Release|x64
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 		{DB35FD31-F92D-4A13-A382-0CD3C6A78F5B}.Debug|Win32.ActiveCfg = Debug|Win32
 		{DB35FD31-F92D-4A13-A382-0CD3C6A78F5B}.Debug|Win32.Build.0 = Debug|Win32
+		{DB35FD31-F92D-4A13-A382-0CD3C6A78F5B}.Debug|x64.ActiveCfg = Debug|x64
+		{DB35FD31-F92D-4A13-A382-0CD3C6A78F5B}.Debug|x64.Build.0 = Debug|x64
 		{DB35FD31-F92D-4A13-A382-0CD3C6A78F5B}.Release|Win32.ActiveCfg = Release|Win32
 		{DB35FD31-F92D-4A13-A382-0CD3C6A78F5B}.Release|Win32.Build.0 = Release|Win32
+		{DB35FD31-F92D-4A13-A382-0CD3C6A78F5B}.Release|x64.ActiveCfg = Release|x64
+		{DB35FD31-F92D-4A13-A382-0CD3C6A78F5B}.Release|x64.Build.0 = Release|x64
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/api-test/API_test.suo b/api-test/API_test.suo
index d7f2c75c0495abcdba0d8ce7946555acb68d5bdc..e1b49c48c78c8c40f955c1296a16a025da3b1b6f 100755
GIT binary patch
delta 1233
zcmcIkOHWf#5T4WCTl#)eKqyc{!~}tshX#vSUMh&O2r(uSBd?emC`Ae>jY(_b!lhx{
zxRb<{E2PG_FaZ@4#f6Xf2mA*vx=<G4cP^E%Kut`Xn>lCh%r`UV&dj;l_H1OOMJMdJ
zknWvWQU-*D14@<sYq-=Oe7!031hR2j*;IXyjNIt2<E&BPlsdp0N|3Wwg}<p46^*bK
zNd)-E_V%{9uuGYPhQr><f}#xj0q{XEPZ>%T4RObCq*w})gRq3aP2gsn>zHu9%$wid
ztII{6I-XBYoc-eBTgD(qjJF*TU@p;d8lfajQ-X!5*i=tJYM@qX<M-voDga1iF|~!|
zw~T=MC=T=_O;I&PX_Rh&r||4(da#etJYB;x30pPwQi?OC4I3HYjPq&4AC($aMjYTp
zb4HgCxh?Y>p+l+-Ylonm-WCxCp#WgjYL>J|xyKRYynR@hq{d)@t%x}7=rc$^GE1#$
zg{1IzM?b$(LIxY&7WABU_FG*L_a^7OGpb63dndjts+Iua)nb=IathvZO^6dbYa8Sh
zw^L2gQEK5qPe6n<UAxD+M|ZM-Q@F-b!FP={OJ2ox<&VX!<+RuRH;lSK<7mv9_XR(3
zXP124-0cYElD=Uf^xDbuB_C7|&TErzb%!856Ieh|lz)a2S{stIh*q3KtKwj-HE2PA
z*PTY;ke;>m@Q~9d=_1Y1Fnnjw)-kLp8q%UHP>icA0S+n(M|_Iv1lBISEe()lw?N$N
zxg3+-xd0zI7NdwZNjDJ%1*9-h4<@V^GukQ7cU^OmLw!cWPGFT|bBbb`_uQ_12<Um(
z#(~(i^Rl^$tBsYb<q;ism3Q#fvaXCA&p5Ki;1LHFBdB>LFu1>T@_MZLA1uq-wN9T7
zi-(_Fk3Q4-`TJt_AIDs~7RZ~~O|oBNc{d;bpTvc{P5Xbb{4uQjCNX#V*HF5_pU3qi
ATL1t6

delta 764
zcmY*X&1(};5TCc%-E5M#$tK;jH6KMpq-ZOf4-1K3n>H!7<`A{?Bq*9(M6_y<8dI7|
zK!qZjxp@#g_GC2&JropLY1K<TdGf#LK`XS*ThbceGW&k>`^~(WH@gkHacVg&v7L5K
z`p8~f<t@3$WPGh0)Ia}xxjy@axd6cSVNL$ZO@b=fE-m~nAI63z<E&ETJst9&z-9cU
z#9}+dxJlH=1on3J0ou`02Tef=J3vIFBjQc9Up^!vo~T1_r;5y2YQAZ<f=>%e-*#Wk
zJ^OJD7c>iPt*MkLs(|Ze23Mkkc+?ZYd_0d0s=nxXud@KjoQw)M4J+a@Gx)$eFKN);
z_HHnVF<j$k7;C$9o8hXQz^cE*MV}%`Ea#?M{wdt>52-#99y6>3CUhsj(|x)q6~o_w
zNu7xci`cybRGpk#64s1K9wzAT(s0Wtaf66ZH(3pqxJZ(^NVT7w=YZS6GCPZR^b5Eg
zGH@|mMXSd|GcxWL85f~~^Wi>r5_9oOEmL+q+MiJtr_B(KN7K%X*31>OWVe)MXoQN#
z>X3sHOu!YWLIv*8`#9W(>o5a%;WpfWI<Z-}3}vXaddG0pce>r^J;yX>O8bNA+vH-(
z!LGKIBjkKQJAR(;#X57z#jF1l3t9p<O^ZIJJzb}I4<Qd06d*yJoq#bIfngYh6yXe^
sG%0D)hRGWx%_5YdXT;Hykfe+xWePM$9VC*eH2pc5cTroyKLels0_*PsegFUf

diff --git a/api-test/API_test.vcproj b/api-test/API_test.vcproj
index abd45c9..dc358fc 100755
--- a/api-test/API_test.vcproj
+++ b/api-test/API_test.vcproj
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
 	ProjectType="Visual C++"
-	Version="9,00"
+	Version="9.00"
 	Name="API_test"
 	ProjectGUID="{DB35FD31-F92D-4A13-A382-0CD3C6A78F5B}"
 	TargetFrameworkVersion="0"
@@ -10,6 +10,9 @@
 		<Platform
 			Name="Win32"
 		/>
+		<Platform
+			Name="x64"
+		/>
 	</Platforms>
 	<ToolFiles>
 	</ToolFiles>
@@ -207,6 +210,199 @@
 				CommandLine="copy Release\API_Test.dll .."
 			/>
 		</Configuration>
+		<Configuration
+			Name="Debug|x64"
+			OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="3"
+				TypeLibraryName=".\Debug/API_test.tlb"
+				HeaderFileName=""
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;API_TEST_EXPORTS"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="2"
+				PrecompiledHeaderThrough="stdafx.h"
+				PrecompiledHeaderFile=".\Debug/API_test.pch"
+				AssemblerListingLocation=".\Debug/"
+				ObjectFile=".\Debug/"
+				ProgramDataBaseFileName=".\Debug/"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile=".\Debug/API_test.dll"
+				LinkIncremental="2"
+				SuppressStartupBanner="true"
+				ModuleDefinitionFile=".\API_test.def"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile=".\Debug/API_test.pdb"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				ImportLibrary=".\Debug/API_test.lib"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+				SuppressStartupBanner="true"
+				OutputFile=".\Debug/API_test.bsc"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|x64"
+			OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+			ConfigurationType="2"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="true"
+				SuppressStartupBanner="true"
+				TargetEnvironment="3"
+				TypeLibraryName=".\Release/API_test.tlb"
+				HeaderFileName=""
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;API_TEST_EXPORTS"
+				StringPooling="true"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="2"
+				PrecompiledHeaderThrough="stdafx.h"
+				PrecompiledHeaderFile=".\Release/API_test.pch"
+				AssemblerListingLocation=".\Release/"
+				ObjectFile=".\Release/"
+				ProgramDataBaseFileName=".\Release/"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile=".\Release/API_test.dll"
+				LinkIncremental="1"
+				SuppressStartupBanner="true"
+				ModuleDefinitionFile=".\API_test.def"
+				ProgramDatabaseFile=".\Release/API_test.pdb"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				ImportLibrary=".\Release/API_test.lib"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+				SuppressStartupBanner="true"
+				OutputFile=".\Release/API_test.bsc"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				Description="Move DLL into place"
+				CommandLine="copy Release\API_Test.dll .."
+			/>
+		</Configuration>
 	</Configurations>
 	<References>
 	</References>
@@ -234,6 +430,22 @@
 						PreprocessorDefinitions=""
 					/>
 				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
 			</File>
 			<File
 				RelativePath="API_test.def"
@@ -260,6 +472,24 @@
 						UsePrecompiledHeader="1"
 					/>
 				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						PreprocessorDefinitions=""
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						PreprocessorDefinitions=""
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
 			</File>
 		</Filter>
 		<Filter
diff --git a/t/00_API.t b/t/00_API.t
index 2a156a5..4c328bb 100755
--- a/t/00_API.t
+++ b/t/00_API.t
@@ -23,7 +23,8 @@ $^E = 0;
 # On cygwin, $$ is different from Win32 process id
 my $cygwin = $^O eq 'cygwin';
 
-$test_dll = Win32::API::Test::find_test_dll('API_test.dll');
+my $test_dll_name = Win32::API::Test::is_perl_64bit() ? 'API_test64.dll' : 'API_test.dll';
+$test_dll = Win32::API::Test::find_test_dll($test_dll_name);
 diag('API_Test.dll found at ('.$test_dll.')');
 ok(-e $test_dll, 'found API_Test.dll');
 
diff --git a/t/01_Struct.t b/t/01_Struct.t
index 8667392..6e418cc 100755
--- a/t/01_Struct.t
+++ b/t/01_Struct.t
@@ -21,7 +21,8 @@ use_ok('Win32::API::Test');
 
 ok(1, 'loaded');
 
-$test_dll = Win32::API::Test::find_test_dll('API_test.dll');
+my $test_dll_name = Win32::API::Test::is_perl_64bit() ? 'API_test64.dll' : 'API_test.dll';
+$test_dll = Win32::API::Test::find_test_dll($test_dll_name);
 ok(-s $test_dll, 'found API_Test.dll');
 
 typedef Win32::API::Struct('simple_struct', qw(
-- 
1.7.0.2.276.g60daf
0001-Split-the-platform-specific-parts-of-Call-into-a-sep.patch (application/octet-stream, 17.1 KB)
From ca5a73c049856b08332a94ddcb3d0e475bbaa886 Mon Sep 17 00:00:00 2001
From: Stephen Bennett <[email protected]>
Date: Tue, 16 Mar 2010 13:38:05 +0000
Subject: [PATCH 1/3] Split the platform-specific parts of Call() into a separate header, so that it can be easily replaced by an x86_64 version

---
 API.xs      |  265 ++++-------------------------------------------------------
 call_i686.h |  227 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 243 insertions(+), 249 deletions(-)
 create mode 100644 call_i686.h

diff --git a/API.xs b/API.xs
index 33f3cb3..8755182 100755
--- a/API.xs
+++ b/API.xs
@@ -21,33 +21,6 @@
 #pragma optimize("", off)
 
 /*
-   "I have a dream."
-   Define one assembler macro for everyone: gcc, Borland C & MSVC
-   Is it possible?
-*/
-
-/* Borland C */
-#if (defined(__BORLANDC__) && __BORLANDC__ >= 452)
-    #define ASM_LOAD_EAX(param,type) \
-        __asm {                      \
-            mov    eax, type param ; \
-            push   eax             ; \
-        }
-/* MSVC compilers */
-#elif defined _MSC_VER
-    /* Disable warning about one missing macro parameter.
-       TODO: How we define a macro with an optional (empty) parameter? */
-    #pragma warning( disable : 4003 )
-    #define ASM_LOAD_EAX(param,type) { \
-    	__asm { mov eax, type param }; \
-    	__asm { push eax };            \
-    }
-/* GCC-MinGW Compiler */
-#elif (defined(__GNUC__))
-    #define ASM_LOAD_EAX(param,...)  asm ("push %0" :: "g" (param));
-#endif
-
-/*
  * some Perl macros for backward compatibility
  */
 #ifdef NT_BUILD_NUMBER
@@ -70,6 +43,8 @@
 #	define call_method(name, flags) perl_call_method(name, flags)
 #endif
 
+#include "call_i686.h"
+
 void pointerCallPack(SV* param, int idx, AV* types) {
 	dSP;
 	SV* type;
@@ -229,32 +204,11 @@ Call(api, ...)
 PPCODE:
     FARPROC ApiFunction;
     APIPARAM *params;
+	APIPARAM retval;
     // APISTRUCT *structs;
     // APICALLBACK *callbacks;
     SV** origST;
 
-    ApiPointer  *ApiFunctionPointer;
-    ApiNumber   *ApiFunctionNumber;
-    ApiFloat    *ApiFunctionFloat;
-    ApiDouble   *ApiFunctionDouble;
-    ApiVoid     *ApiFunctionVoid;
-    ApiInteger  *ApiFunctionInteger;
-
-    /* int    iParam; */
-    long   lParam;
-    float  fParam;
-    double dParam;
-    /* char   cParam; */
-    char  *pParam;
-    LPBYTE ppParam;
-
-    int    iReturn;
-    long   lReturn;
-    float  fReturn;
-    double dReturn;
-    char  *pReturn;
-    char  *cReturn; // a copy of pReturn
-
     HV*		obj;
     SV**	obj_proc;
     SV**	obj_proto;
@@ -504,183 +458,10 @@ PPCODE:
 #endif
 			}
 		}
-
-		/* #### PUSH THE PARAMETER ON THE (ASSEMBLER) STACK #### */
-        words_pushed = 0;
-        for(i = nin; i >= 0; i--) {
-            switch(params[i].t) {
-            case T_POINTER:
-            case T_STRUCTURE:
-                pParam = params[i].p;
-#ifdef WIN32_API_DEBUG
-                printf("(XS)Win32::API::Call: parameter %d (P) is %s\n", i, pParam);
-#endif
-                ASM_LOAD_EAX(pParam, dword ptr);
-                words_pushed++;
-                break;
-            case T_POINTERPOINTER:
-                ppParam = params[i].b;
-#ifdef WIN32_API_DEBUG
-                printf("(XS)Win32::API::Call: parameter %d (P) is %s\n", i, ppParam);
-#endif
-                ASM_LOAD_EAX(ppParam, dword ptr);
-                words_pushed++;
-                break;
-            case T_NUMBER:
-            case T_CHAR:
-                lParam = params[i].l;
-#ifdef WIN32_API_DEBUG
-                printf("(XS)Win32::API::Call: parameter %d (N) is %ld\n", i, lParam);
-#endif
-                ASM_LOAD_EAX(lParam);
-                words_pushed++;
-                break;
-            case T_FLOAT:
-                fParam = params[i].f;
-#ifdef WIN32_API_DEBUG
-                printf("(XS)Win32::API::Call: parameter %d (F) is %f\n", i, fParam);
-#endif
-                ASM_LOAD_EAX(fParam);
-                words_pushed++;
-                break;
-            case T_DOUBLE:
-                dParam = params[i].d;
-#ifdef WIN32_API_DEBUG
-                printf("(XS)Win32::API::Call: parameter %d (D) is %f\n", i, dParam);
-#endif
-#if (defined(_MSC_VER) || defined(BORLANDC))
-                __asm {
-                    mov   eax, dword ptr [dParam + 4]  ;
-                    push  eax                          ;
-                    mov   eax, dword ptr [dParam]      ;
-                    push  eax                          ;
-                };
-#elif (defined(__GNUC__))
-		/* probably uglier than necessary, but works */
-		asm ("pushl %0":: "g" (((unsigned int*)&dParam)[1]));
-		asm ("pushl %0":: "g" (((unsigned int*)&dParam)[0]));
-		/* { 
-		  int idc;
-		  printf ("dParam = ");
-		  for (idc = 0; idc < sizeof(dParam); idc++) {
-		    printf(" %2.2x",((unsigned char*)&dParam)[idc]);
-		  } 
-		  printf("   %f\n", dParam);
-		} */
-#endif
-                words_pushed++;
-                words_pushed++;
-                break;
-            case T_CODE:
-                lParam = params[i].l;
-#ifdef WIN32_API_DEBUG
-                printf("(XS)Win32::API::Call: parameter %d (K) is 0x%x\n", i, lParam);
-#endif
-                ASM_LOAD_EAX(lParam);
-                words_pushed++;
-                break;
-            }
-        }
     }
 
-	/* #### NOW CALL THE FUNCTION #### */
-    switch(tout) {
-    case T_NUMBER:
-        ApiFunctionNumber = (ApiNumber *) ApiFunction;
-#ifdef WIN32_API_DEBUG
-    	printf("(XS)Win32::API::Call: Calling ApiFunctionNumber()\n");
-#endif
-        lReturn = ApiFunctionNumber();
-        break;
-    case T_FLOAT:
-        ApiFunctionFloat = (ApiFloat *) ApiFunction;
-#ifdef WIN32_API_DEBUG
-    	printf("(XS)Win32::API::Call: Calling ApiFunctionFloat()\n");
-#endif
-#ifdef WIN32_API_DEBUG
-        printf("(XS)Win32::API::Call: ApiFunctionFloat returned %f\n", fReturn);
-#endif
-        break;
-    case T_DOUBLE:
-        ApiFunctionDouble = (ApiDouble *) ApiFunction;
-#ifdef WIN32_API_DEBUG
-    	printf("(XS)Win32::API::Call: Calling ApiFunctionDouble()\n");
-#endif
-#if (defined(_MSC_VER) || defined(__BORLANDC__))
-		/*
-			_asm {
-			call    dword ptr [ApiFunctionDouble]
-			fstp    qword ptr [dReturn]
-		}
-		*/
-	    dReturn = ApiFunctionDouble();
-#elif (defined(__GNUC__))
-	    dReturn = ApiFunctionDouble();
-            /*
-              asm ("call *%0"::"g" (ApiFunctionDouble));
-              asm ("fstpl %st(0)");
-              asm ("movl %0,(%esp)");
-            */
-	/* XST_mNV(0, (double) dReturn); */
-#endif
-#ifdef WIN32_API_DEBUG
-       printf("(XS)Win32::API::Call: ApiFunctionDouble returned %f\n", dReturn);
-#endif
-        break;
-    case T_POINTER:
-        ApiFunctionPointer = (ApiPointer *) ApiFunction;
-#ifdef WIN32_API_DEBUG
-    	printf("(XS)Win32::API::Call: Calling ApiFunctionPointer()\n");
-#endif
-        pReturn = ApiFunctionPointer();
-#ifdef WIN32_API_DEBUG
-        printf("(XS)Win32::API::Call: ApiFunctionPointer returned 0x%x '%s'\n", pReturn, pReturn);
-#endif
-		/* #### only works with strings... #### */
-		cReturn = (char *) safemalloc(strlen(pReturn));
-		strcpy(cReturn, pReturn);
-
-        break;
-    case T_INTEGER:
-        ApiFunctionInteger = (ApiInteger *) ApiFunction;
-#ifdef WIN32_API_DEBUG
-    	printf("(XS)Win32::API::Call: Calling ApiFunctionInteger()\n");
-#endif
-        iReturn = ApiFunctionInteger();
-#ifdef WIN32_API_DEBUG
-    	printf("(XS)Win32::API::Call: ApiFunctionInteger returned %d\n", iReturn);
-#endif
-        break;
-    case T_VOID:
-    default:
-#ifdef WIN32_API_DEBUG
-    	printf("(XS)Win32::API::Call: Calling ApiFunctionVoid() (tout=%d)\n", tout);
-#endif
-        ApiFunctionVoid = (ApiVoid *) ApiFunction;
-        ApiFunctionVoid();
-        break;
-    }
-
-    // cleanup stack for _cdecl type functions.
-    if (c_call) {
-#if (defined(_MSC_VER) || defined(__BORLANDC__))
-        _asm {
-            mov eax, dword ptr words_pushed
-            shl eax, 2
-            add esp, eax
-        }
-#elif (defined(__GNUC__))
-        asm ( 
-            "movl %0, %%eax\n" 
-            "shll $2, %%eax\n" 
-            "addl %%eax, %%esp\n" 
-
-            : /* no output */ 
-            : "m" (words_pushed) /* input */ 
-            : "%eax" /* modified registers */ 
-        );
-#endif
-    }
+	retval.t = tout;
+	Call_asm(ApiFunction, params, nin, &retval, c_call);
 
 	/* #### THIRD PASS: postfix pointers/structures #### */
     for(i = 0; i <= nin; i++) {
@@ -724,54 +505,40 @@ PPCODE:
     switch(tout) {
     case T_NUMBER:
 #ifdef WIN32_API_DEBUG
-	   	printf("(XS)Win32::API::Call: returning %d.\n", lReturn);
+	   	printf("(XS)Win32::API::Call: returning %d.\n", retval.l);
 #endif
-        XSRETURN_IV(lReturn);
+        XSRETURN_IV(retval.l);
         break;
     case T_FLOAT:
 #ifdef WIN32_API_DEBUG
-	   	printf("(XS)Win32::API::Call: returning %f.\n", fReturn);
+	   	printf("(XS)Win32::API::Call: returning %f.\n", retval.f);
 #endif
-        XSRETURN_NV((double) fReturn);
+        XSRETURN_NV((double) retval.f);
         break;
     case T_DOUBLE:
 #ifdef WIN32_API_DEBUG
-	   	printf("(XS)Win32::API::Call: returning %f.\n", dReturn);
-#endif
-#if (defined(_MSC_VER) || defined(__BORLANDC__))
-	_asm {
-	    call    dword ptr [ApiFunctionDouble] ;
-	    fstp    qword ptr [dReturn]           ;
-    	}
-    	/*  XSRETURN_NV(dReturn); */
-#elif (defined(__GNUC__))
-        dReturn = ApiFunctionDouble();
-        /*
-              asm ("call *%0"::"g" (ApiFunctionDouble));
-              asm ("fstpl %st(0)");
-              asm ("movl %0,(%esp)");
-        */
- 	/* XST_mNV(0, dReturn); */
+	   	printf("(XS)Win32::API::Call: returning %f.\n", retval.d);
 #endif
+		XSRETURN_NV(retval.d);
         break;
     case T_POINTER:
-		if(pReturn == NULL) {
+		if(retval.p == NULL) {
 #ifdef WIN32_API_DEBUG
 	   	printf("(XS)Win32::API::Call: returning NULL.\n");
 #endif
 			XSRETURN_IV(0);
 		} else {
 #ifdef WIN32_API_DEBUG
-		printf("(XS)Win32::API::Call: returning 0x%x '%s'\n", cReturn, cReturn);
+		printf("(XS)Win32::API::Call: returning 0x%x '%s'\n", retval.p, retval.p);
 #endif
-	        XSRETURN_PV(cReturn);
+	        XSRETURN_PV(retval.p);
 	    }
         break;
     case T_INTEGER:
 #ifdef WIN32_API_DEBUG
-	   	printf("(XS)Win32::API::Call: returning %d.\n", iReturn);
+	   	printf("(XS)Win32::API::Call: returning %d.\n", retval.l);
 #endif
-        XSRETURN_IV(iReturn);
+        XSRETURN_IV(retval.l);
         break;
     case T_VOID:
     default:
diff --git a/call_i686.h b/call_i686.h
new file mode 100644
index 0000000..54a8d90
--- /dev/null
+++ b/call_i686.h
@@ -0,0 +1,227 @@
+
+/*
+   "I have a dream."
+   Define one assembler macro for everyone: gcc, Borland C & MSVC
+   Is it possible?
+*/
+
+/* Borland C */
+#if (defined(__BORLANDC__) && __BORLANDC__ >= 452)
+    #define ASM_LOAD_EAX(param,type) \
+        __asm {                      \
+            mov    eax, type param ; \
+            push   eax             ; \
+        }
+/* MSVC compilers */
+#elif defined _MSC_VER
+    /* Disable warning about one missing macro parameter.
+       TODO: How we define a macro with an optional (empty) parameter? */
+    #pragma warning( disable : 4003 )
+    #define ASM_LOAD_EAX(param,type) { \
+    	__asm { mov eax, type param }; \
+    	__asm { push eax };            \
+    }
+/* GCC-MinGW Compiler */
+#elif (defined(__GNUC__))
+    #define ASM_LOAD_EAX(param,...)  asm ("push %0" :: "g" (param));
+#endif
+
+void Call_asm(FARPROC ApiFunction, APIPARAM *params, int nparams, APIPARAM *retval, BOOL c_call)
+{
+    ApiPointer  *ApiFunctionPointer;
+    ApiNumber   *ApiFunctionNumber;
+    ApiFloat    *ApiFunctionFloat;
+    ApiDouble   *ApiFunctionDouble;
+    ApiVoid     *ApiFunctionVoid;
+    ApiInteger  *ApiFunctionInteger;
+
+    /* int    iParam; */
+    long   lParam;
+    float  fParam;
+    double dParam;
+    /* char   cParam; */
+    char  *pParam;
+    LPBYTE ppParam;
+
+	char *pReturn;
+
+	int words_pushed;
+	int i;
+
+	/* #### PUSH THE PARAMETER ON THE (ASSEMBLER) STACK #### */
+	words_pushed = 0;
+	for(i = nparams; i >= 0; i--) {
+		switch(params[i].t) {
+		case T_POINTER:
+		case T_STRUCTURE:
+			pParam = params[i].p;
+#ifdef WIN32_API_DEBUG
+			printf("(XS)Win32::API::Call: parameter %d (P) is %s\n", i, pParam);
+#endif
+			ASM_LOAD_EAX(pParam, dword ptr);
+			words_pushed++;
+			break;
+		case T_POINTERPOINTER:
+			ppParam = params[i].b;
+#ifdef WIN32_API_DEBUG
+			printf("(XS)Win32::API::Call: parameter %d (P) is %s\n", i, ppParam);
+#endif
+			ASM_LOAD_EAX(ppParam, dword ptr);
+			words_pushed++;
+			break;
+		case T_NUMBER:
+		case T_CHAR:
+			lParam = params[i].l;
+#ifdef WIN32_API_DEBUG
+			printf("(XS)Win32::API::Call: parameter %d (N) is %ld\n", i, lParam);
+#endif
+			ASM_LOAD_EAX(lParam);
+			words_pushed++;
+			break;
+		case T_FLOAT:
+			fParam = params[i].f;
+#ifdef WIN32_API_DEBUG
+			printf("(XS)Win32::API::Call: parameter %d (F) is %f\n", i, fParam);
+#endif
+			ASM_LOAD_EAX(fParam);
+			words_pushed++;
+			break;
+		case T_DOUBLE:
+			dParam = params[i].d;
+#ifdef WIN32_API_DEBUG
+			printf("(XS)Win32::API::Call: parameter %d (D) is %f\n", i, dParam);
+#endif
+#if (defined(_MSC_VER) || defined(BORLANDC))
+			__asm {
+				mov   eax, dword ptr [dParam + 4]  ;
+				push  eax                          ;
+				mov   eax, dword ptr [dParam]      ;
+				push  eax                          ;
+			};
+#elif (defined(__GNUC__))
+	/* probably uglier than necessary, but works */
+	asm ("pushl %0":: "g" (((unsigned int*)&dParam)[1]));
+	asm ("pushl %0":: "g" (((unsigned int*)&dParam)[0]));
+	/* { 
+	  int idc;
+	  printf ("dParam = ");
+	  for (idc = 0; idc < sizeof(dParam); idc++) {
+		printf(" %2.2x",((unsigned char*)&dParam)[idc]);
+	  } 
+	  printf("   %f\n", dParam);
+	} */
+#endif
+			words_pushed++;
+			words_pushed++;
+			break;
+		case T_CODE:
+			lParam = params[i].l;
+#ifdef WIN32_API_DEBUG
+			printf("(XS)Win32::API::Call: parameter %d (K) is 0x%x\n", i, lParam);
+#endif
+			ASM_LOAD_EAX(lParam);
+			words_pushed++;
+			break;
+		}
+	}
+
+	/* #### NOW CALL THE FUNCTION #### */
+    switch(retval->t) {
+    case T_NUMBER:
+        ApiFunctionNumber = (ApiNumber *) ApiFunction;
+#ifdef WIN32_API_DEBUG
+    	printf("(XS)Win32::API::Call: Calling ApiFunctionNumber()\n");
+#endif
+        retval->l = ApiFunctionNumber();
+        break;
+    case T_FLOAT:
+        ApiFunctionFloat = (ApiFloat *) ApiFunction;
+#ifdef WIN32_API_DEBUG
+    	printf("(XS)Win32::API::Call: Calling ApiFunctionFloat()\n");
+#endif
+#ifdef WIN32_API_DEBUG
+        printf("(XS)Win32::API::Call: ApiFunctionFloat returned %f\n", retval->f);
+#endif
+        break;
+    case T_DOUBLE:
+        ApiFunctionDouble = (ApiDouble *) ApiFunction;
+#ifdef WIN32_API_DEBUG
+    	printf("(XS)Win32::API::Call: Calling ApiFunctionDouble()\n");
+#endif
+#if (defined(_MSC_VER) || defined(__BORLANDC__))
+		/*
+			_asm {
+			call    dword ptr [ApiFunctionDouble]
+			fstp    qword ptr [dReturn]
+		}
+		*/
+	    retval->d = ApiFunctionDouble();
+#elif (defined(__GNUC__))
+	    retval->d = ApiFunctionDouble();
+            /*
+              asm ("call *%0"::"g" (ApiFunctionDouble));
+              asm ("fstpl %st(0)");
+              asm ("movl %0,(%esp)");
+            */
+	/* XST_mNV(0, (double) dReturn); */
+#endif
+#ifdef WIN32_API_DEBUG
+       printf("(XS)Win32::API::Call: ApiFunctionDouble returned %f\n", retval->d);
+#endif
+        break;
+    case T_POINTER:
+        ApiFunctionPointer = (ApiPointer *) ApiFunction;
+#ifdef WIN32_API_DEBUG
+    	printf("(XS)Win32::API::Call: Calling ApiFunctionPointer()\n");
+#endif
+        pReturn = ApiFunctionPointer();
+#ifdef WIN32_API_DEBUG
+        printf("(XS)Win32::API::Call: ApiFunctionPointer returned 0x%x '%s'\n", pReturn, pReturn);
+#endif
+		/* #### only works with strings... #### */
+		retval->p = (char *) safemalloc(strlen(pReturn));
+		strcpy(retval->p, pReturn);
+
+        break;
+    case T_INTEGER:
+        ApiFunctionInteger = (ApiInteger *) ApiFunction;
+#ifdef WIN32_API_DEBUG
+    	printf("(XS)Win32::API::Call: Calling ApiFunctionInteger()\n");
+#endif
+        retval->l = ApiFunctionInteger();
+#ifdef WIN32_API_DEBUG
+    	printf("(XS)Win32::API::Call: ApiFunctionInteger returned %d\n", retval->l);
+#endif
+        break;
+    case T_VOID:
+    default:
+#ifdef WIN32_API_DEBUG
+    	printf("(XS)Win32::API::Call: Calling ApiFunctionVoid() (tout=%d)\n", retval->t);
+#endif
+        ApiFunctionVoid = (ApiVoid *) ApiFunction;
+        ApiFunctionVoid();
+        break;
+    }
+
+    // cleanup stack for _cdecl type functions.
+    if (c_call) {
+#if (defined(_MSC_VER) || defined(__BORLANDC__))
+        _asm {
+            mov eax, dword ptr words_pushed
+            shl eax, 2
+            add esp, eax
+        }
+#elif (defined(__GNUC__))
+        asm ( 
+            "movl %0, %%eax\n" 
+            "shll $2, %%eax\n" 
+            "addl %%eax, %%esp\n" 
+
+            : /* no output */ 
+            : "m" (words_pushed) /* input */ 
+            : "%eax" /* modified registers */ 
+        );
+#endif
+    }
+}
+
-- 
1.7.0.2.276.g60daf
0002-Initial-x86_64-support-in-Win32-API.patch (application/octet-stream, 7.2 KB)
From 840d56f16b63db9537471da3798f0425af3455ed Mon Sep 17 00:00:00 2001
From: Stephen Bennett <[email protected]>
Date: Tue, 16 Mar 2010 18:06:23 +0000
Subject: [PATCH 2/3] Initial x86_64 support in Win32::API.

---
 API.xs                |    9 ++++-
 Makefile.PL           |   22 ++++++++++
 call_asm_x64_msvc.asm |   70 +++++++++++++++++++++++++++++++
 call_i686.h           |    2 +-
 call_x86_64.h         |  111 +++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 212 insertions(+), 2 deletions(-)
 create mode 100644 call_asm_x64_msvc.asm
 create mode 100644 call_x86_64.h

diff --git a/API.xs b/API.xs
index 8755182..b655daa 100755
--- a/API.xs
+++ b/API.xs
@@ -43,7 +43,13 @@
 #	define call_method(name, flags) perl_call_method(name, flags)
 #endif
 
+#if defined(_M_AMD64) || defined(__x86_64)
+#include "call_x86_64.h"
+#elif defined(_M_IX86) || defined(__i386)
 #include "call_i686.h"
+#else
+#error "Don't know what architecture I'm on."
+#endif
 
 void pointerCallPack(SV* param, int idx, AV* types) {
 	dSP;
@@ -460,8 +466,9 @@ PPCODE:
 		}
     }
 
+	/* nin is actually number of parameters minus one. I don't know why. */
 	retval.t = tout;
-	Call_asm(ApiFunction, params, nin, &retval, c_call);
+	Call_asm(ApiFunction, params, nin + 1, &retval, c_call);
 
 	/* #### THIRD PASS: postfix pointers/structures #### */
     for(i = 0; i <= nin; i++) {
diff --git a/Makefile.PL b/Makefile.PL
index 661cb31..d7d95f6 100755
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -5,6 +5,11 @@
 my $running_on_windows = $^O eq 'MSWin32' || $^O eq 'cygwin';
 die qq(OS unsupported\n) unless $running_on_windows;
 
+# Must be a better way to do this, surely...
+use Config;
+my $is_64bit_build = ($Config{ptrsize} == 8);
+my $is_msvc_compiler = ($Config{cc} =~ /cl/);
+
 use ExtUtils::MakeMaker;
 WriteMakefile(
     'NAME'	=> 'Win32::API',
@@ -37,6 +42,14 @@ WriteMakefile(
         eval "$ExtUtils::MakeMaker::VERSION" >= 6.10_03
             ? ( 'NO_META' => 1 )
             : ()
+    ),
+    (
+        eval $is_64bit_build
+	    ? ( $is_msvc_compiler
+		    ? ( 'OBJECT' => '$(BASEEXT)$(OBJ_EXT) call_asm_x64_msvc$(OBJ_EXT)' )
+		    : ( 'OBJECT' => '$(BASEEXT)$(OBJ_EXT) call_asm_x64_gnu$(OBJ_EXT)' )
+		)
+	    : ( )
     )
 );
 
@@ -48,3 +61,12 @@ sub MY::depend
     return "\ntest_dynamic :: \n\t\$(CHMOD) \$(PERM_RWX) API_test.dll";
 }
 
+sub MY::postamble
+{
+    return unless $is_64bit_build;
+    return <<'EOM';
+.asm$(OBJ_EXT):
+	$(AS) $(ASFLAGS) -c $<
+
+EOM
+}
diff --git a/call_asm_x64_msvc.asm b/call_asm_x64_msvc.asm
new file mode 100644
index 0000000..7f8b2b0
--- /dev/null
+++ b/call_asm_x64_msvc.asm
@@ -0,0 +1,70 @@
+.CODE
+
+; void Call_x64_real(FARPROC ApiFunction, size_t *int_registers, double *float_registers, stackitem *stack, size_t nstack, size_t *iret, double *dret)
+Call_x64_real PROC FRAME
+
+    ; store register parameters
+    mov qword ptr[rsp+32], r9  ; stack
+    mov qword ptr[rsp+24], r8  ; float_registers
+    mov qword ptr[rsp+16], rdx ; int_registers
+    mov qword ptr[rsp+8],  rcx ; ApiFunction
+
+    mov qword ptr[rsp-16], rbp
+    mov rbp, rsp
+    .SETFRAME rbp, 0
+    .ENDPROLOG
+
+    sub rsp, 32
+
+    ; Load up integer registers first...
+    mov rax, qword ptr [rbp+16]
+
+    mov rcx, qword ptr [rax]
+    mov rdx, qword ptr [rax+8]
+    mov r8,  qword ptr [rax+16]
+    mov r9,  qword ptr [rax+24]
+
+    ; Now floating-point registers
+    mov rax, qword ptr [rbp+24]
+    movsd xmm0, qword ptr [rax]
+    movsd xmm1, qword ptr [rax+8]
+    movsd xmm2, qword ptr [rax+16]
+    movsd xmm3, qword ptr [rax+24]
+
+    ; Now the stack
+    mov rsi, qword ptr [rbp+32]
+    mov rax, qword ptr [rbp+40]
+
+    ; Except not if there isn't any
+    test rax, rax
+    jz docall
+    sub rax, 1
+
+copystack:
+    mov r10, qword ptr [rsi+8*rax]
+    push r10
+    sub rax, 1
+    test rax, rax
+    jnz copystack
+
+docall:
+    ; And call
+    sub rsp, 32
+    mov r10, qword ptr [rbp+8]
+    call r10
+
+    ; Store return value
+    mov r10, qword ptr [rbp+48]
+    mov qword ptr [r10], rax
+    mov r10, qword ptr [rbp+56]
+    movsd qword ptr [r10], xmm0
+
+    ; Cleanup
+    mov rsp, rbp
+    mov rbp, qword ptr [rsp-16]
+
+    ret
+
+Call_x64_real ENDP
+
+END
diff --git a/call_i686.h b/call_i686.h
index 54a8d90..06a8268 100644
--- a/call_i686.h
+++ b/call_i686.h
@@ -50,7 +50,7 @@ void Call_asm(FARPROC ApiFunction, APIPARAM *params, int nparams, APIPARAM *retv
 
 	/* #### PUSH THE PARAMETER ON THE (ASSEMBLER) STACK #### */
 	words_pushed = 0;
-	for(i = nparams; i >= 0; i--) {
+	for(i = nparams-1; i >= 0; i--) {
 		switch(params[i].t) {
 		case T_POINTER:
 		case T_STRUCTURE:
diff --git a/call_x86_64.h b/call_x86_64.h
new file mode 100644
index 0000000..901d63e
--- /dev/null
+++ b/call_x86_64.h
@@ -0,0 +1,111 @@
+
+/* size_t because it's definitely pointer-size. AFAIK no other int type is on both MSVC and gcc */
+typedef union {
+	size_t i;
+	double d;
+	float f;
+} stackitem;
+
+void Call_x64_real(FARPROC, size_t *, double *, stackitem *, size_t, size_t *, double *);
+
+enum {
+	available_registers = 4
+};
+
+void Call_asm(FARPROC ApiFunction, APIPARAM *params, int nparams, APIPARAM *retval, BOOL c_call)
+{
+	size_t nRegisters = 0, nStack = 0;
+	size_t required_registers = 0, required_stack = 0;
+
+	double float_registers[available_registers] = { 0., 0., 0., 0. };
+	size_t int_registers[available_registers] = { 0, 0, 0, 0 };
+
+	stackitem *stack = NULL;
+
+	size_t iret;
+	double dret;
+
+	int i;
+
+	required_registers = nparams > available_registers ? available_registers : nparams;
+	required_stack = nparams > available_registers ? nparams - available_registers : 0;
+
+	if (required_stack)
+	{
+		stack = malloc(required_stack * sizeof(*stack));
+		memset(stack, 0, required_stack * sizeof(*stack));
+	}
+
+	for (i = 0; i < nparams; ++i)
+	{
+		if (i < available_registers)
+		{
+			/* First four arguments go in registers, either integer or floating point. */
+			switch (params[i].t)
+			{
+				case T_NUMBER:
+				case T_INTEGER:
+				case T_CHAR:
+					int_registers[i] = params[i].l;
+					break;
+				case T_POINTER:
+				case T_STRUCTURE:
+					int_registers[i] = params[i].p;
+					break;
+				case T_FLOAT:
+					float_registers[i] = params[i].f;
+					break;
+				case T_DOUBLE:
+					float_registers[i] = params[i].d;
+					break;
+			}
+		}
+		else
+		{
+			switch (params[i].t)
+			{
+				case T_NUMBER:
+				case T_INTEGER:
+					stack[i - available_registers].i = params[i].l;
+					break;
+				case T_POINTER:
+				case T_STRUCTURE:
+					stack[i - available_registers].i = params[i].p;
+					break;
+				case T_CHAR:
+					stack[i - available_registers].i = params[i].c;
+					break;
+				case T_FLOAT:
+					stack[i - available_registers].f = params[i].f;
+					break;
+				case T_DOUBLE:
+					stack[i - available_registers].d = params[i].d;
+					break;
+			}
+		}
+	}
+
+	Call_x64_real(ApiFunction, int_registers, float_registers, stack, required_stack, &iret, &dret);
+
+	switch (retval->t)
+	{
+		case T_NUMBER:
+		case T_INTEGER:
+			retval->l = iret;
+			break;
+		case T_POINTER:
+			retval->p = iret;
+			break;
+		case T_CHAR:
+			retval->c = iret;
+			break;
+		case T_FLOAT:
+			retval->f = dret;
+			break;
+		case T_DOUBLE:
+			retval->d = dret;
+			break;
+	}
+}
+
+
-- 
1.7.0.2.276.g60daf
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.